2015-09-27 9 views
9

これは理論的な質問ですが、データ構造が変更できないこと、そしてこれが間違いなくクエリを実行する方法であると仮定します。この質問は、の詳細な理解を得るために、実際にはのように、whereフィルタを動的に作成するのではなく、実際にこのようなクエリの結果を得たいと思っています。動的な量のEctoクエリを作成するフィルタ

各車に "BD324"または "GM512"などのIDを含むmanufacturer_id列があり、 "BD" & "GM"が接頭辞とみなされるCarテーブルのデータベースを想像してください。

manufacturer_idの接頭辞が与えられた接頭辞のセットと一致すると車が返されるように、車のテーブルを検索する必要があります。だから、接頭辞のリストを与えられた:

prefixes = ["BD", "GM", "EX", "RD", "DE"] 

記載されているもののいずれかで始まるmanufacturer_idを持っているすべての車を返したい..we'd。すなわち(LIKE x または好きy または好き)。

次エリクシール/エクトのコードは、1つの接頭辞を検索します:

search_prefix = Enum.at(prefixes, 0) <> "%" 
from c in Car, where: like(c.manufacturer_id, ^search_prefix) 

はどのように我々はprefixesリストに基づいてwhere句を構築して行くのでしょうか?

答えて

4

Ectoにはクエリの動的部分をORと簡単に結合する方法がないようですが、私は何か不足している可能性があります。私が間違っていれば私を修正してください。

:、あなたが fragmentを使用することができますエクトを持つクエリのこの種を作成するには

SELECT * from cars 
WHERE manufacturer_id LIKE ANY(ARRAY['BD%', 'GM%', 'EX%', 'RD%', 'DE%']); 

しかし、あなたは私が構築する読みやすくかつシンプルな両方であると主張同等ANYクエリを、使用することができます

prefixes_like = prefixes |> Enum.map(&"#{&1}%") 
from c in Car, 
    where: fragment("? LIKE ANY(?)", c.manufacturer_id, ^prefixes_like), 
    select: c 
+0

ありがとう! IRCでJoséに話しかけてください。これは確かに(少なくとも今のところは)行く方法です。あなたが持っている要件がORではなくANDであるなら、acc:でqからのreduce: 'Enum.reduce prefixes、query、fn prefix、acc - >を使うことができます:like(q.manufacturer_id、^(接頭辞< > "%"))end' –

+1

またはEcto 2.1でクエリが追加されました。https://github.com/elixir-ecto/ecto/commit/640e8f5f7f97eab68e4eebcd517803f71d90ebc1#commitcomment-18945603 –

3

あなたは、データ変換としてクエリを構成すると考えることができます:

prefixes -> query with multiple where conditions 

これを行うには、1つのデータ構造を別のものに減らす必要があり、Ecto 2は、必要に応じてor_whereを提供します。以下は

例です。

def filter_by_prefixes(query, prefixes) do 
    Enum.reduce prefixes, query, fn prefix, query -> 
    filter_by_prefix(query, prefix) 
    end 
end 

def filter_by_prefix(query, prefix) do 
    or_where(query, [c], like(c.manufacturer_id, ^"#{prefix}%")) 
end 

# Then build the query 
Car |> filter_by_prefixes(prefixes) 
+0

ありがとうございました!これはエクト2の前に書かれましたが、これは確かに今行く方法です。 –

関連する問題