3

少し背景を説明します。Rails 3.0.7、Postgres 9.0、および MetaWhere/MetaSearch 1.0.4 を使用しています。

データベースにクエリを実行するときに一意のレコードを取得する際に、非常にイライラする問題があります。私は次のように3つのモデルを持っています:

class Car < ActiveRecord::Base
  has_many    :sellers, :through => :adverts, :uniq => true
  has_many    :adverts, :dependent => :destroy
end

class Seller < ActiveRecord::Base
  has_many :cars, :through => :adverts, :uniq => true
  has_many :adverts
end

class Advert < ActiveRecord::Base
  belongs_to :car, :autosave => false
  belongs_to :seller, :autosave => false
end

ここまでは順調ですね。今、私がやりたいことは、Fiat Panda のすべての車を検索することです (car の:brand、:model_name 属性)。これはうまくいっています。しかし、sellers テーブルからの情報も追加したい場合、問題が発生し始めます - 車が重複しています!!! 私がすることは次のとおりです。

Car.includes(:adverts, :sellers).where(:brand >> 'Fiat', :model_name >> 'Panda', :sellers => [:kind >> 'Dealer'])

「データベースは、各車に接続されているすべての売り手からどの種類を選択するかをどのように知る必要があるのでしょうか?」しかし、それらはすべて同じであるため、属性値を取得する最初の販売者であろうと最後の販売者であろうと関係ありません。.debug_sql を実行すると、次のようになります。

SELECT cars.*, sellers.*, adverts.* FROM cars LEFT OUTER JOIN adverts ON adverts.car_id = cars.id LEFT OUTER JOIN adverts sellers_cars_join ON cars.id = sellers_cars_join.car_id LEFT OUTER JOIN sellers ON sellers.id = sellers_cars_join.seller_id WHERE cars.brand = 'Fiat' AND cars.model_name = 'Panda' AND sellers.kind = 'Dealer'

もちろん、これにより重複が発生しますが、完全に理にかなっていますが、どうすれば解決できますか? -それは私が望むものではないからです。

これには 2 つの解決策が考えられます。まず、レールのような方法で実行できる場合

SELECT DISTINCT(cars.id), cars.*, sellers.*, adverts.* FROM cars LEFT....

それは私に正しいものを与えるようです。

2番目 ご覧のとおり、関連付けに :uniq => true を追加しましたが、これは、私の例でのみ機能することがわかる限り、売り手に次のように述べて車を求めた場合:

Seller.includes(:adverts, :cars).where(:cars => [:brand >> 'Fiat'], :cars => [:model_name >> 'Panda'], :kind >> 'Dealer')

しかし、これについてはまったくわかりません!また、metawhere/metasearch についてはどうでしょうか。これにも干渉しているのではないかと心配しています。

4

1 に答える 1

5

includes は LEFT OUTER JOIN を実行し、実際に重複を作成します。クエリの後に各 @car.seller にアクセスする必要がない場合 (n+1 クエリの問題)、代わりに結合を使用してください。

Car.joins(:sellers).
    where(:cars => {:brand => 'Fiat', 
                    :model_name => 'Panda'}, 
          :sellers => {:kind => 'Dealer'})

joins は INNER JOIN を実行するため、重複することはありません。

于 2011-09-22T13:25:54.573 に答える