1

私はしばらくこれを試してきましたが、Activerecord ではうまくいかないようです。

asset_idとのペアの配列が与えられた場合、両方の属性とが一致asset_typeする場合にのみ、両方の属性を持つクラスをクエリします。asset_idasset_type

与えられた配列

[[4,"Logo"],[1,"Image"]]

SQLを生成したい

SELECT "asset_attachments".* FROM "asset_attachments" WHERE ((asset_id,asset_type) IN ((4,'Logo'),(1,'Image')))

次のように where を使用して文字列を手動で入力することで、これを行うことができます。

AssetAttachment.where("(asset_id,asset_type) IN ((4,'Logo'),(1,'Image'))")

しかし、任意の長さとアセット タイプ/ID の配列で使用しようとしています。

これまで私は試しました

AssetAttachment.where([:asset_id, :asset_type] => [[4,"Logo"],[1,"Image"]])

NoMethodError: undefined method `to_sym' for [:asset_id, :asset_type]:Array

AssetAttachment.where("(asset_id,asset_type)" => [[4,"Logo"],[1,"Image"]])

ActiveRecord::StatementInvalid: PG::Error: ERROR: column asset_attachments.(asset_id,asset_type) does not exist

AssetAttachment.where("(asset_id,asset_type) IN (?,?)",[[4,"Logo"],[1,"Image"]])

ActiveRecord::PreparedStatementInvalid: wrong number of bind variables (1 for 2) in: (asset_id,asset_type) IN (?,?)

誰もこれを行う方法を知っていますか? 前もって感謝します

4

1 に答える 1

1

セットと配列

問題の核心は、セット配列を不可能な方法で混在させていることです。

elem IN (...)..セットを期待しています。
elem = ANY(...)..配列が必要です。

unnest()配列をセットに変換するために使用できます。集合関数
を 使用して、セットを配列に変換できます。array_agg()

エラー

ここでは、から配列を形成しようとしています(asset_id, asset_type):

AssetAttachment.where([:asset_id, :asset_type] => [[4,"Logo"],[1,"Image"]])

.. 配列は同じ型で構成されている必要があるため、これは不可能です。ただし、数値定数と文字列定数は明らかに扱います (実際の型は秘密にしておきます)。

ここでは、二重引用符で囲んで単一の列名"(asset_id, asset_type)"として強制します。

AssetAttachment.where("(asset_id,asset_type)" => [[4,"Logo"],[1,"Image"]])

そして最後に、2 つの に対して 1 つのバインド変数を提供してます?

AssetAttachment.where("(asset_id,asset_type) IN (?,?)",[[4,"Logo"],[1,"Image"]])

有効な SQL

純粋な SQL では、次のいずれかが機能します。

SELECT * FROM asset_attachments
WHERE  (asset_id, asset_type) IN ((4, 'Logo'), (1, 'Image'));

SELECT * FROM asset_attachments
WHERE  (asset_id, asset_type) IN (VALUES(4, 'Logo'), (1, 'Image'));

SELECT * FROM asset_attachments
WHERE  (asset_id, asset_type) = ANY (ARRAY[(4, 'Logo'), (1, 'Image')]);

可能な一致の長いリストがある場合は、明示的なJOIN方が高速であることが証明されます。

SELECT *
FROM   asset_attachments
JOIN   (VALUES(4, 'Logo'), (1, 'Image')) AS v(asset_id, asset_type)
                                       USING (asset_id, asset_type)

AR の有効な構文

私は Postgres の専門家で、AR はあまり得意ではありません。この単純な形式はうまくいくかもしれません:

AssetAttachment.where("(asset_id,asset_type) IN ((?,?),(?,?))", 4,"Logo",1,"Image")

これがうまくいくかどうかわからない、一重引用符または二重引用符についてもわからない:

AssetAttachment.where((:asset_id, :asset_type) => [(4,'Logo'),(1,'Image')])
于 2013-05-26T16:03:16.147 に答える