タグ付けによるカテゴリと多くのタグを含む投稿があります。タグとカテゴリにはname
、キーの翻訳を含むhstoreファイルが含まれています。
純粋なEctoクエリで、たとえば「pl」キーを使用して関連post.tags
するJSONをプリロードして選択するにはどうすればよいですか? tag.name
この場合、「pl」をパラメーターとしてロケールキーを渡したいのですが、それを補間する方法がわかりません。何も機能しません。
defmodule Myapp.Tag do
use Myapp.Web, :model
schema "tags" do
field :name, :map
has_many :taggings, Myapp.Tagging
has_many :posts, through: [:taggings, :post]
belongs_to :post, Myapp.Post
timestamps
end
end
defmodule Myapp.Tagging do
use Myapp.Web, :model
schema "taggings" do
belongs_to :post, Myapp.Post
belongs_to :tag, Myapp.Tag
end
end
defmodule Myapp.Post do
use Myapp.Web, :model
schema "posts" do
field :title, :string
belongs_to :category, Myapp.Category
has_many :taggings, Myapp.Tagging
has_many :tags, through: [:taggings, :tag]
timestamps
end
end
テスト:
post = Repo.get!(Post, id) |> Repo.preload([:tags, :category])
post.tags # => "tags":[{"name":{"pl":"narty","en":"ski"}},{"name":{"pl":"wspinaczka","en":"climbing"}}]
#how preload all with selected key?
posts = Post
|> Repo.all
|> Repo.preload(tags: from(t in Myapp.Tag, select: fragment("?::json->?", t.name, "pl")))
エラー:
** (BadMapError) expected a map, got: "narty"
(stdlib) :maps.find(:id, "narty")
(elixir) lib/map.ex:27: Map.fetch!/2
(elixir) lib/enum.ex:1387: Enum."-reduce/3-lists^foldl/2-0-"/3
(elixir) lib/enum.ex:1043: anonymous fn/3 in Enum.map/2
(elixir) lib/enum.ex:1387: Enum."-reduce/3-lists^foldl/2-0-"/3
(elixir) lib/enum.ex:1043: Enum.map/2
(elixir) lib/enum.ex:1043: anonymous fn/3 in Enum.map/2
(elixir) lib/enum.ex:1387: Enum."-reduce/3-lists^foldl/2-0-"/3
(elixir) lib/enum.ex:1043: Enum.map/2
(stdlib) erl_eval.erl:669: :erl_eval.do_apply/6
(stdlib) erl_eval.erl:438: :erl_eval.expr/5
(iex) lib/iex/evaluator.ex:117: IEx.Evaluator.handle_eval/5
をお願いします:
post.tags # => "tags":["narty","wspinaczka"]
移行:
defmodule Myapp.Repo.Migrations.CreateTag do
use Ecto.Migration
def change do
create table(:tags) do
add :name, :map
add :category_id, references(:categories)
timestamps
end
end
end
defmodule Myapp.Repo.Migrations.CreateJoinTableTaggings do
use Ecto.Migration
def change do
create table(:taggings) do
add :post_id, references(:posts)
add :tag_id, references(:tags)
end
create index(:taggings, [:post_id, :tag_id])
end
end
アップデート
Ecto 2.0 は、プリロード クエリでカスタム選択フィールドをサポートしているため、これが答えです。
|> Repo.preload(tags: from(t in Myapp.Tag, select: %{id: t.id, data: fragment("?::json->?", t.name, "pl")}))