2017-10-23 3 views
1

Versuch, mit Ecto embeds_many zu experimentieren, und funktioniert gut, bis ich auf einige Daten im eingebetteten Feld abfragen muss.Abfrage in Ecto embeds_viele Assoziation

So habe ich so etwas wie ein product dass embeds_manycategories

schema "products" do 
    field :code, :string, null: false 

    embeds_many :categories, Category, 
    on_replace: :delete, 
    primary_key: {:id, :binary_id, autogenerate: false} 
    do 
    field :name, :string 
    end 
end 

def create_changeset(%Product{} = product, attrs) do 
    product 
    |> cast(attrs, [:code]) 
    |> cast_embed(:categories, with: &attributes_changeset/2) 
end 

def attributes_changeset(%{} = product_attribute, attrs) do 
    product_attribute 
    |> cast(attrs, [:id, :name]) 
end 

Nach Produkte zu schaffen ich mit so etwas wie diese Tabelle in der Postgres

ID-Code Kategorien

1 11  {"{\"id\": \"dress\", \"name\": \"Dress\"}, 
      "{\"id\": \"shirt\", \"name\": \"Shirt\"}} 
2 22  {"{\"id\": \"dress\", \"name\": \"Dress\"}} 

So landen jetzt möchte ich alle products wo id == "dress" abfragen, und natürlich würde ich mag die 2 Ergebnisse oben zu bekommen.

Ich habe mit so etwas wie dies experimentiert: q = from p in Product, where: fragment("? @> ?", p.categories, '{"id": "dress"}') sondern verwandelt das Array in ganzen Zahlen: operator does not exist: jsonb[] @> integer[] ... WHERE (p0."categories" @> ARRAY[123,34,105,100,34,58,32,34,100,114,101,115,115,34,125])

oder dass: q = from p in Product, where: fragment("? @> ?", p.categories, "[{\"id\": \"dress\"}]"), bekommen malformed array literal: "[{"id": "dress"}]"

Was hoffte ich war so etwas wie: q = from p in Product, where: fragment("? -> 'id' = ?", p.categories, "rochie") aber nicht sicher, ob das funktioniert.

Antwort

2

Seit categories ist ein jsonb[] hier, nicht ein einfaches json, der Betreiber @> nicht direkt mit ihm arbeiten. Sie können ANY und <@ verwenden zu tun, was Sie wollen:

where: fragment("? <@ ANY(?)", ~s|{"id": "dress"}|, p.categories) 

Diese '{"id": "dress"}' <@ ? für jede Kategorie in den Kategorien Array laufen und return true, wenn einer von ihnen entsprechen.

(~s|"a"| ist nur ein sauberer Weg "\"a\"" zu schreiben.)

+0

Thanks so much! es funktioniert perfekt. Wenn ich Ihnen noch eine Frage stellen könnte, wie würde ich nach etwas suchen wie "id in [" dress "," shirt "]' Grundsätzlich für viele Kategorien zu überprüfen. – iacobSon

+0

Ich kann mir keine Lösung für eine beliebige Anzahl von Fällen vorstellen .. ANY ist nur auf der RHS erlaubt. Für eine festgelegte Anzahl von Fällen können Sie das gleiche Prädikat, z. 'fragment ("? <@ ANY (?) ", ~ s | {" id ":" Kleid "} |, p.categories) oder Fragment ("? <@ ANY (?) ", ~ s | { "id": "shirt"} |, p.categories) '. – Dogbert

+0

ja, das 'oder' sieht wie eine gute Lösung aus. Nochmals vielen Dank für Ihre Hilfe. – iacobSon

Verwandte Themen