2017-11-15 1 views
1

Ectoが間違った結果を返す理由がわかりません。Ecto.Query結合が非常に多くのINNER JOINを生成します

SELECT u0."email", u0."id", r2."name", c1."name" 
FROM "users" AS u0 
INNER JOIN "access_lists" AS a4 ON a4."user_id" = u0."id" 
INNER JOIN "companies" AS c1 ON a4."company_id" = c1."id" 
INNER JOIN "access_lists" AS a5 ON a5."company_id" = c1."id" 
INNER JOIN "roles" AS r2 ON a5."role_id" = r2."id" 
INNER JOIN "access_lists" AS a6 ON a6."role_id" = r2."id" 
INNER JOIN "assets" AS a3 ON a6."asset_id" = a3."id" 
WHERE ((u0."id" = $1) AND (a3."id" = $2)) 
GROUP BY c1."id", u0."id", r2."id" [2, 1] 

このクエリの結果は、これがある

間違っています: 私は物事をめちゃくちゃにされるかもしれないと、これは、それが生成する私のEcto.Query

from u in User, 
     join: c in assoc(u, :companies), 
     join: r in assoc(c, :roles), 
     join: a in assoc(r, :assets), 
     where: u.id == ^2 and a.id == ^1, 
     group_by: [c.id, u.id, r.id], 
     select: {u.email, u.id, r.name, c.name} 

ある

に参加します正しいクエリ:

SELECT u0.email, u0.id, r2.name, c1.name, a6.asset_name , a6.id as asset_id 
FROM users AS u0 
INNER JOIN access_lists AS a4 ON a4.user_id = u0.id 
INNER JOIN assets AS a6 ON a4.asset_id = a6.id 
INNER JOIN companies AS c1 ON a4.company_id = c1.id 
INNER JOIN roles AS r2 ON a4.role_id = r2.id 
WHERE ((u0.id = 2) AND (a6.id = 1)) 
Group By u0.id, r2.id, c1.id, a6.id 

ここでは、スキーマです:

するaccesslist:

schema "access_lists" do 
     belongs_to :user, Db.User 
     belongs_to :role, Db.Role 
     belongs_to :asset, Db.Asset 
     belongs_to :project, Db.Project 
     belongs_to :company, Db.Company 

     timestamps() 
    end 

ユーザー:

many_to_many :roles, Db.Role, join_through: Db.AccessList 
many_to_many :assets, Db.Asset, join_through: Db.AccessList 
many_to_many :projects, Db.Project, join_through: Db.AccessList   
many_to_many :companies, Db.Company, join_through: Db.AccessList 

資産:

many_to_many :users, Db.User, join_through: Db.AccessList 
many_to_many :companies, Db.Company, join_through: Db.AccessList 
many_to_many :roles, Db.Role, join_through: Db.AccessList 
many_to_many :projects, Db.Project, join_through: Db.AccessList 

会社:

many_to_many :users, Db.User, join_through: Db.AccessList 
    many_to_many :assets, Db.Asset, join_through: Db.AccessList 
    many_to_many :roles, Db.Role, join_through: Db.AccessList 
    many_to_many :projects, Db.Project, join_through: Db.AccessList 

役割:

many_to_many :users, Db.User, join_through: Db.AccessList 
    many_to_many :assets, Db.Asset, join_through: Db.AccessList 
    many_to_many :projects, Db.Project, join_through: Db.AccessList 
    many_to_many :companies, Db.Company, join_through: Db.AccessList 

ここでは図である。 enter image description here

+0

明示的エクトを助けるために、 'access_lists'に参加しようとする気にしませんか? – mudasobwa

+0

アソシエーションはどのように宣言されていますか? –

+0

@MikeBuhotそれらのすべては多くのものがたくさんあります。 –

答えて

0

私はこれが動作し、私はしかし、私はなぜわからない、正しい結果を得る

from u in User, 
     join: acl in AccessList, on: acl.user_id == u.id, 
     join: c in Company, on: acl.company_id == c.id, 
     join: r in Role, on: acl.role_id == r.id, 
     join: a in Asset, on: acl.asset_id == a.id, 
     where: u.id == ^2 and a.id == ^1, 
     group_by: [c.id, u.id, r.id], 
     select: {u.email, u.id, r.name, c.name} 

を使用していました。

そして、なぜ私は、すべての結合を定義する必要があると

は、なぜ私はスキーマを見ずに代わり

+0

'roles:' assoc(acl、:companies) 'と同様の' roles'と 'assets'はあなたのために働きますか? – Dogbert

+0

@Dogbertいいえ、それはしませんでした。私の質問 'from'クエリを参照してください。それは誤った結果で戻ってきた。私が明示的に結合を説明するとき、それは働いた。 –

+0

@Dogbert私はスキーマ –

1

join assocを使用することはできませんん、それは言うことは困難ですが、私はいくつかの推測を行うことができます。 AccessListは、Userと企業、ロール、およびアセットの間の結合テーブルであるため、Ectoはそれ以降の結合で以前のAccessListクエリを再利用するほど十分にはわかりません。

はこのようにそれをマッピングし、明示的に試してみてください。

from u in User, 
    join: acl in assoc(u, :access_lists), 
    join: c in assoc(acl, :companies), 
    join: r in assoc(acl, :roles), 
    join: a in assoc(acl, :assets), 
    where: u.id == ^2 and a.id == ^1, 
    group_by: [c.id, u.id, r.id], 
    select: {u.email, u.id, r.name, c.name} 
+0

を追加しましたこれは私が 'スキームDb.User'上で' access_lists'の関連付けを見つけることができませんでした –

+0

私は今スキーマを追加しました –