sql >> Databáze >  >> RDS >> PostgreSQL

Modelování velkých objektů PostgreSQL v Rails

Pokud používáte ActiveRecord dodávaný s Rails s jedním z jeho adaptérů, jediné formální mapování typu databáze na typ Rails nebo Ruby, ke kterému dochází, je obvykle definováno v NATIVE_DATABASE_TYPES konstanta v adaptéru, která je vrácena prostřednictvím jeho native_database_types metoda. Pro PostgreSQL v Rails 3.2.x je to v ActiveRecord::ConnectionAdapters::PostgreSQLAdapter který je zde . Takže pro tento adaptér se typ „binary“ v Rails mapuje na typ „bytea“ v PG. U některých typů můžete tento typ databáze, na který se mapuje, přepsat pomocí drahokamu zvaného activerecord-native_db_types_override . Ale chceme používat velké objekty, takže...

Migrace

Jak poznamenal Jim Deville v komentářích, můžete zadat vlastní typovaný sloupec v tabulce jako:

t.column :some_oid, 'blob_oid', :null => false

Pokud potřebujete udělat ještě více, co je nestandardní, můžete také použít execute("SQL GOES HERE;") k vytvoření tabulky pomocí přímého SQL. A pokud máte existující starší schéma nebo změny SQL, které byly provedeny mimo migrace, zvažte použití structure.sql (config.active_record.schema_format = :sql možnost v config/application.rb a pak proveďte:rake db:structure:dump ).

Čtení/zápis/kontrola délky/mazání velkých objektů

Zkopírováno s některými úpravami pro objasnění atd. z:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :

Aktualizováno :můžeme, ale nemusíme vložit začátek před lo_read/lo_write/lo_lseek a udělat lo_close v bloku secure, protože podle dokumentace PG "Všechny popisovače velkých objektů, které zůstanou otevřené na konci transakce, budou automaticky uzavřeny." (díky Diogo za tuto informaci)

    require 'pg'

    ...

    def read
      (...).transaction do
        lo = connection.lo_open(identifier)
        content = connection.lo_read(lo, file_length)
        connection.lo_close(lo)
        content
      end
    end

    def write(file)
      (...).transaction do
        lo = connection.lo_open(identifier, ::PG::INV_WRITE)
        size = connection.lo_write(lo, file.read)
        connection.lo_close(lo)
        size
      end
    end

    def delete
      connection.lo_unlink(identifier)
    end

    def file_length
      (...).transaction do
        lo = connection.lo_open(identifier)
        size = connection.lo_lseek(lo, 0, 2)
        connection.lo_close(lo)
        size
      end
    end

Místo connection , použijte nezpracované spojení z modelu nebo základny, např. ActiveRecord::Base.connection.raw_connection (viz toto ).

(...).transaction je volání transakce na modelu nebo bázi, např. ActiveRecord::Base.transaction (viz toto ).

identifier je oid, který musíte buď předat/nastavit, nebo jej získat pouhým provedením connection.lo_creat .

Další příklady/informace:

Poslední a některé odpovědi zde naznačují, že byste možná chtěli zvážit ukládání velkých souborů odděleně od DB, např. abyste mohli využívat cloudové úložiště. Pokud však pouze ukládáte cesty/ID k externím souborům, které nejsou spravované DB, ztratíte konzistenci ACID (jeden nebo více záznamů DB může ukazovat na jeden nebo více souborů, které tam nejsou, nebo může existovat jeden nebo více souborů, které nemají jeden nebo více přidružených záznamů v databázi). Dalším argumentem pro ukládání souborů v souborovém systému je, že můžete streamovat soubory, ale velký objekt PG ukládá soubory na souborovém systému způsobem spravovaným postgresem, aby byla zajištěna konzistence ACID a umožněno streamování (což nemůžete udělat s normálním BLOBem /Binární typ Rails). Takže záleží jen na tom; někteří považují ukládání v odděleném úložišti pomocí odkazů na cestu za lepší možnost a někteří preferují konzistenci ACID prostřednictvím velkých objektů.

Snadný způsob

Stačí použít CarrierWave a carrierwave-postgresql .




  1. Mysql_fetch_array( $result, MYSQL_BOTH ) není přesné

  2. 5 důvodů, proč je Microsoft Access skvělý pro začínající podniky

  3. Co je nového v MariaDB 10.4

  4. Jak odečíst minuty od hodnoty data a času v MariaDB