5

ユーザーが PostgreSQL の JSONB レコード タイプを使用してカスタム フィールドを作成できる、フェニックスの Rails で最初に作成したアプリケーションを再実装しています。例として、次の (簡略化された表現) スキーマがあります。

クライアント

  • ID (整数)
  • クライアント タイプ ID (int)
  • 名前 (文字列)
  • 情報 (jsonb)

クライアントの種類

  • ID (整数)
  • 名前 (文字列)

カスタム フィールド定義

  • ID (整数)
  • クライアント タイプ ID (int)
  • キー (文字列)
  • ラベル(文字列)

Rails では、ActiveRecord が魔法のように JSONB をハッシュとの間で変換します。これにより、JSONB を使用してカスタム フィールドのスキーマレス セットを非常に簡単に格納できます。

たとえば、クライアントの種類ごとに異なるカスタム フィールドを定義できます。ユーザーに情報を表示するときに、定義をループしてキーを取得し、それを使用して JSONB ドキュメントからデータを取得します。

私は Ecto を使用してこれを達成する方法を見つけようとしていましたが、埋め込まれたスキーマを見る必要があるように見えます (ここで良い情報を見ました)。実行時にこれにカスタム量のフィールドを追加できますか?

これについてのアドバイスを探していました。これまでのところ、これは私が遭遇した唯一の実際の障害であり、ほとんどすぐには解決されません。

ありがとうございます。

4

2 に答える 2

2

データ構造を少し変更することでこれを解決できました。カスタム フィールドは JSONB 配列になりました。これにより、embeds_many の関係を非常に洗練されたものにすることができます。私は実際、リンク ( http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/ ) のドキュメントを十分に読んでいませんでした。データが十分に構造化されていませんでした。

したがって、次のような JSONB 列を持つ代わりに

{
  "name":"Something",
  "address":"123 Fake St"
}

のように見える

[
  {
    "field":"name",
    "value":"Something"
  },
  {
    "field":"address",
    "value":"123 Fake St"
  },
]

これは私のユースケースには最適なオプションのようですが、より多くのスペースを占有します (Ecto は必要な ID フィールドをバックグラウンドで各オブジェクトに追加して整合性を確保するため)。

この構造に変更した後、モデルを作成し、リンクごとに関連付けただけです。一言で言えば、次のようになります。

defmodule UserManager.CustomField do
  use Ecto.Model

  embedded_schema do
    field :field
    field :value
  end

  @required_fields ~w(field value)
  @optional_fields ~w()

  @doc """
  Creates a changeset based on the `model` and `params`.

  If no params are provided, an invalid changeset is returned
  with no validation performed.
  """
  def changeset(model, params \\ :empty) do
    model |> cast(params, @required_fields, @optional_fields)
  end
end

defmodule UserManager.Client do
  # ...
  schema "clients" do
    # ...
    embeds_many :custom_fields, UserManager.CustomField
    # ...
  end
  # ...
end
于 2015-09-22T20:51:23.623 に答える
0

Postgrex のReadme には、JSON 拡張機能の例が含まれています。

于 2015-09-22T19:42:59.310 に答える