私は、有効なエクトクエリに次のSQLクエリを「翻訳」トラブルを抱えている:ElixirのEcto Queryフォーマットでこのクエリを表現する方法は?
SELECT *
FROM file_modules
WHERE file_id =
(SELECT f.file_id
FROM files AS f
LEFT JOIN file_modules AS fm ON f.file_id = fm.file_id
WHERE f.storage_id = '20:1:0:86d:1591:c89c:512:de52' AND fm.name = 'bruteforce'
ORDER BY f.version DESC
LIMIT 1)
私が進むべき道は二つにこのクエリを分割することであると信じています。ここで私が試したものです:
q1 =
File
|> where([f], f.storage_id == ^storage_id)
|> join(:left, [f], fm in FileModule, f.file_id == fm.file_id)
|> where([..., fm], fm.name == ^module_name)
|> order_by([..., fm], desc: fm.version)
|> select([fm], fm.file_id)
|> limit(1)
# q1 works and returns the expected file_id
q2 =
q1
|> subquery()
|> where([fm, fm2], fm.file_id == fm2.file_id) # Here's where I'm stuck
|> preload([..., m], [modules: m])
q1
は、次のEcto.Query結果を持っています
#Ecto.Query<from f0 in Helix.Software.Model.File,
left_join: f1 in Helix.Software.Model.FileModule, on: f0.file_id == f1.file_id,
where: f0.storage_id == ^(storage_id),
where: f1.name == ^:bruteforce, order_by: [desc: f1.version], limit: 1,
select: f0.file_id>
私の問題は、q2
であると思われます。入力としてq1
の の結果を使用するには、どのようにフォーマットする必要がありますか?
ありがとうございます。
私はこの質問は私の根底にあるスキーマにとらわれないですが、ここではそれがあると信じて:
schema "files" do
field :file_id, ID,
primary_key: true
field :name, :string
field :path, :string
field :software_type, Constant
field :file_size, :integer
field :storage_id, Storage.ID
field :crypto_version, :integer
field :full_path, :string
belongs_to :type, SoftwareType,
foreign_key: :software_type,
references: :software_type,
define_field: false
belongs_to :storage, Storage,
foreign_key: :storage_id,
references: :storage_id,
define_field: false
has_many :modules, FileModule,
foreign_key: :file_id,
references: :file_id,
on_replace: :delete
timestamps()
end
schema "file_modules" do
field :file_id, File.ID,
primary_key: true
field :name, Constant,
primary_key: true
field :version, :integer
belongs_to :file, File,
foreign_key: :file_id,
references: :file_id,
define_field: false,
on_replace: :update
end
コメントにJablanovićで述べたように、それは、ORMの抽象化が時々失敗している可能性があります。その場合、上記の生のsqlを使用することは可能ですか?
1)File.IDとStorage.IDの型をキャストすると、醜い文字列の連結を避けることができますか?
2)結果を返すと、プリロードまたはこの結果をスキーマに保存しますか?私が考えている
インターフェースのようなものです:Ecto.Adapters.SQL.query/4の例を1として
q = "SELECT * FROM files WHERE file_id = $1", ^file_id
file = Repo.get(q) |> Repo.preload()
file.file_id # Returns file id
私は1どのように約2を達成することができますように、それが見えますか?
私の最終目標は、file_idとstorage_idを安全にキャストし、%File {}スキーマを正しく使用し、ロードされた関連付けをfile.modules
にして、上記のネストされたSQLクエリを使用することです。
fragment
を使用して正しくキャストできる、より良いインターフェースがストアドプロシージャまたはビューから得られることに注意してください。しかし、私はまだそのデータをスキーマに「プリロードする」ことに問題があると感じています。
は、なぜあなたは別に2つのクエリを実行しませんか?あなたは多くを失うことはありません。 –
これは回避策として私が今やっていることですが、サブクエリを使うことができなければ、極端に制限されてしまいます。私はEctoがサポートしていると確信しています。だから、それがどのように機能するかを考え出すのは私の問題です。しかし、これまでのところ、Ectoサブクエリに関するいくつかの記事やガイドを読んだ後でも、私はまだそれをつかむのに苦労しています。 –
残念ながら、過去に複数のORMを使って作業した後は、SQLクエリーをORM式に変換しようとしている人もいます(https://stackoverflow.com/a/41429995/82592)。 。時には、SQLを現状のまま文字列やデータベースビューの形式で保存することで、あなたと将来のメンテナーに無駄な時間を浪費することがあります。 –