摘要:及其以上版本可以存儲類似這樣的非結構化數據作為一個的數據封裝器提供了這些非結構話的數據到原生數據類型的序列化和反序列化嵌入的記錄具有所有常規模型所具有的東西比如結構化的字段生命周期回調變更集下面研究如何把結構嵌入到模型當中使用嵌入單個結構可
Postgres 9.4 及其以上版本可以存儲類似 arrays, json, jsonb 這樣的非結構化數據. Ecto 作為一個 Elixir 的數據封裝器, 提供了這些非結構話的數據到 Elixir 原生數據類型的序列化和反序列化. 嵌入的記錄具有所有常規模型所具有的東西, 比如結構化的字段, 生命周期回調, 變更集. 下面研究如何把結構嵌入到 Ecto 模型當中.
使用 embeds_one 嵌入單個結構可以使用 embeds_one 嵌入單個結構到 Ecto 模型當中. 嵌入的字段必須是 :map 這種非結構化的的數據類型. 在 Postgres 中, Ecto 使用了 jsonb 作為底層數據庫字段的數據類型.
20160430043543_create_table_account.exs
defmodule EctoTest.Repo.Migrations.CreateTableAccount do use Ecto.Migration def change do create table(:accounts) do add :name, :string add :settings, :map # 遷移腳本里面數據類型需要設置為 :map, # 這樣 Postgrex 適配器才能正確的把它映射到 jsonb[] 數據類型 end end end
執行項目目錄中的 ./migrate 腳本, 內容如下
#!/bin/bash mix ecto.migrate -r EctoTest.Repo
? ecto_test git:(master) ? ./migrate 12:38:10.930 [info] == Running EctoTest.Repo.Migrations.CreateTableAccount.change/0 forward 12:38:10.930 [info] create table accounts 12:38:10.943 [info] == Migrated in 0.0s
定義模型
defmodule EctoTest.Model.Account do use Ecto.Schema alias EctoTest.Model.Settings schema "accounts" do field :name embeds_one :settings, Settings end end
定義嵌入到 EctoTest.Model.Account 模型中的字段:
defmodule EctoTest.Model.Settings do use Ecto.Model embedded_schema do field :email_signature field :send_emails, :boolean end end
嵌入的記錄行為上和電信的關聯(associations)一樣, 只是它只能夠通過變更集(changeset)來更新和刪除
插入數據測試
# 模擬 EctoTest.get/1 返回一個 %EctoTest.Model.Account() 結構 account = %EctoTest.Model.Account{name: "test"} # 創建Settings結構 settings = %EctoTest.Model.Settings{email_signature: "developerworks", send_emails: true} # 創建變更集 changeset = Ecto.Changeset.change(account) # 嵌入 changeset = Ecto.Changeset.put_embed(changeset, :settings, settings) # 插入數據 changeset |> EctoTest.Repo.insert!
當父記錄保存時, 會自動地的調用嵌入模型(Settings模型)中的 changeset/2 函數.
嵌入的記錄可以通過.符號來訪問, 因此不必考慮在一般的關聯關系中的鏈接JOIN和預加載(preload)的問題:
account = Repo.get!(EctoTest.Model.Account, 1) account.settings #=> %Settings{...}使用 embeds_many 嵌入多個結構
embeds_many 允許你嵌入一個 Ecto 結構數組到一個關系數據庫字段中. 在數據庫底層 Postgres 使用了 array 和 jsonb 數據類型來實現 embeds_many.
defmodule EctoTest.Repo.Migrations.CreateTablePeople do use Ecto.Migration def up do create table(:people) do add :name, :string add :address, {:array, :map}, default: [] end end def down do drop table(:people) end end
定義 Person, Address 模型:
defmodule EctoTest.Model.Person do use Ecto.Schema alias EctoTest.Model.Address schema "people" do field :name embeds_many :addresses, Address end def test_insert do changeset = Ecto.Changeset.change(%__MODULE__{}) addresses = [ %Address{street_name: "20 Foobar Street",city: "Boston",state: "MA",zip_code: "02111"}, %Address{street_name: "1 Finite Loop", city: "Cupertino",state: "CA",zip_code: "95014"} ] changeset = Ecto.Changeset.put_embed(changeset, :addresses, addresses) Repo.insert!(changeset) end end defmodule EctoTest.Model.Address do use Ecto.Schema embedded_schema do field :street_name field :city field :state field :zip_code end end
設置多對多字段的值
iex(1)> EctoTest.Model.Person.test_insert 13:44:25.731 [debug] QUERY OK db=9.4ms INSERT INTO "people" ("addresses") VALUES ($1) RETURNING "id" [[%{city: "Boston", id: "2de7fd44-a1cf-44cd-a060-d6260325ac90", state: "MA", street_name: "20 Foobar Street", zip_code: "02111"}, %{city: "Cupertino", id: "bb65fd96-f1b1-4f0d-a92e-712884e40a7c", state: "CA", street_name: "1 Finite Loop", zip_code: "95014"}]] %EctoTest.Model.Person{__meta__: #Ecto.Schema.Metadata<:loaded>, addresses: [%EctoTest.Model.Address{city: "Boston", id: "2de7fd44-a1cf-44cd-a060-d6260325ac90", state: "MA", street_name: "20 Foobar Street", zip_code: "02111"}, %EctoTest.Model.Address{city: "Cupertino", id: "bb65fd96-f1b1-4f0d-a92e-712884e40a7c", state: "CA", street_name: "1 Finite Loop", zip_code: "95014"}], id: 1, name: nil}
像 has_many 一樣訪問:
iex(2)> person = EctoTest.Repo.get!(EctoTest.Model.Person, 1) 13:45:04.634 [debug] QUERY OK db=1.4ms decode=9.5ms SELECT p0."id", p0."name", p0."addresses" FROM "people" AS p0 WHERE (p0."id" = $1) [1] %EctoTest.Model.Person{__meta__: #Ecto.Schema.Metadata<:loaded>, addresses: [%EctoTest.Model.Address{city: "Boston", id: "2de7fd44-a1cf-44cd-a060-d6260325ac90", state: "MA", street_name: "20 Foobar Street", zip_code: "02111"}, %EctoTest.Model.Address{city: "Cupertino", id: "bb65fd96-f1b1-4f0d-a92e-712884e40a7c", state: "CA", street_name: "1 Finite Loop", zip_code: "95014"}], id: 1, name: nil} iex(3)> person.addresses [%EctoTest.Model.Address{city: "Boston", id: "2de7fd44-a1cf-44cd-a060-d6260325ac90", state: "MA", street_name: "20 Foobar Street", zip_code: "02111"}, %EctoTest.Model.Address{city: "Cupertino", id: "bb65fd96-f1b1-4f0d-a92e-712884e40a7c", state: "CA", street_name: "1 Finite Loop", zip_code: "95014"}]權衡
記錄的嵌入是 Ecto 提供的多個強大的能之一. 很容易給嵌入的記錄添加字段, 不需要運行時修改數據庫結構. 這些都是優勢, 但有的場景下也會帶來一些問題, 因此需要權衡是否應該使用嵌入.
使用非結構化數據, 丟失了SQL數據庫提供的關系特性, 例如, 一個記錄只能嵌入到一個父表中, 因此不能使用嵌入建模多對多關系, 也不能使用數據庫約束, 雖然可以在應用程序中檢查數據的完整性, 但是更好的方式是在數據庫級別進行驗證, 以保障數據的完整性.
示例代碼https://github.com/developerworks/ecto_test
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/38940.html
摘要:要解決的問題數據庫中存儲的行數超過了類型所能容納的數量因此需要采用類型的整數作為主鍵的取值范圍為到的取值范圍為到完整的字段的數據類型可以參考這里遷移腳本要點的參數要設置為通過宏指定主鍵列類型為模型的聲明要點主鍵要聲明為類型完 要解決的問題 數據庫中存儲的行數超過了 serial 類型所能容納的數量, 因此需要采用 bigserial 類型的整數作為主鍵serial 的取值范圍為: 1...
摘要:簡介數據格式空間數據的文本標識空間數據的二進制標識基于對象表示法的地理空間信息數據交換格式的庫提供了上述三種格式的相互轉換函數配置添加依賴配置擴展創建刪除擴展的移植腳本腳本內容執行移植插入數據軌跡點粵獲取經緯度粵查詢聯系如何查詢字段例 簡介 數據格式 Abbr Fullname Description WKT Well Known Text 空間數據的文本標識 WKB ...
摘要:本文以用一個在數據庫中保存圖片信息為例展示如何向中插入二進制數據首先我們要知道中唯一一種二進制數據的類型為表示字節數組或字節序列對應于和中的下面是一個示例遷移腳本這里也可以為實際上在執行數據庫中字段的類型就是當然除了圖片文件以外你還 本文以用一個在數據庫中保存圖片信息為例, 展示如何向 Postgresql 中插入二進制數據. showImg(https://segmentfault....
摘要:使用作為主鍵的目的降低類型這種自增線性特征作為隨機生成的字符串讓更離散增強系統的反爬蟲能力至少避免通過的線性增加來爬取內容這種最簡單的爬取方式使用主鍵的是那種方式各有優缺點可按實際需求自行權衡在應用程序中生成并插入到數據庫通過使用擴展自動生 使用UUID作為主鍵的目的 降低Serial類型這種自增ID線性特征, UUID作為隨機生成的字符串, 讓ID更離散, 增強系統的反爬蟲能力(至...
摘要:這個速查表主要是分享互聯網上一些比較常用的工具和技術常用內容,如編輯器的快捷鍵的命令行的選擇器的屬性等,這個列表簡單收集了常用的工具,可以收藏用于平時的備忘錄,需要用到的時候可以及時查閱。 這個速查表主要是分享互聯網上一些比較常用的工具和技術常用內容,如編輯器的快捷鍵、git的命令行、jQuery的API選擇器、CSS的flexbox屬性等,這個列表簡單收集了常用的工具,可以收藏用于平...
閱讀 1985·2021-09-26 10:19
閱讀 3257·2021-09-24 10:25
閱讀 1641·2019-12-27 11:39
閱讀 1929·2019-08-30 15:43
閱讀 670·2019-08-29 16:08
閱讀 3509·2019-08-29 16:07
閱讀 909·2019-08-26 11:30
閱讀 1273·2019-08-26 10:41