我有两个模型,与habtm相关(实际上使用has_many:through在两端,以及一个连接表)。我需要检索与两个模型B都关联的所有模型。我不想让modelb 1的所有modelas与modelb 2的所有modelas连接。我确实希望所有与modelb 1和modelb 2关联的modela。它不仅限于2个modelbs,还可以多达50个modelbs,因此必须进行缩放。
我可以用各种类比来描述这个问题,我认为这比前一段更好地描述了我的问题:

* Find all books that were written by all 3 authors together.
* Find all movies that had the following 4 actors in them.
* Find all blog posts that belonged to BOTH the Rails and Ruby categories for each post.
* Find all users that had all 5 of the following tags: funny, thirsty, smart, thoughtful, and quick.   (silly example!)
* Find all people that have worked in both San Francisco AND San Jose AND New York AND Paris in their lifetimes.

我想了很多方法来实现这一点,但它们效率很低,而且很不受欢迎。
举一个类似的例子,比如说最后一个,你可以做一些事情,比如查询每个城市的所有人,然后在每个数组中找到每个数组中的项目。这至少是5个查询,所有这些查询的数据都会传输回应用程序,然后应用程序必须密集地相互比较所有5个数组(循环次数太多!).真恶心,对吧?
另一种可能的解决方案是将查找结果相互链接,这基本上与上面的方法相同,但不会消除多个查询和处理。另外,如果用户提交了高达50个选项的复选框或值,您将如何动态化链?看起来很脏。你需要一个循环。同样,这将加大搜索时间。
显然,如果可能的话,我们希望让数据库为我们执行此操作,因此,人们建议我只需输入多个条件。不幸的是,你只能做一个或与habtm典型。
我遇到的另一个解决方案是使用搜索引擎,比如sphinx或ultrasphinx。对于我的特殊情况,我觉得这太过分了,我宁愿避免。我仍然觉得应该有一个解决方案,让用户手工查询任意数量的modelbs并找到所有modela。
你将如何解决这个问题?

最佳答案

你可以这样做:
从模型A生成查询,连接模型B(通过连接模型),筛选具有您要查找的值之一的模型B,即将它们放入或(即where ModelB = 'ModelB_1' or ModelB = 'ModelB_2')。使用此查询,结果集将有多个“modela”行,满足每个modelb条件时正好有一行。
向查询中添加所需的modela列的group by条件(如果愿意,甚至包括所有列)。每行的count()等于满足的ModelB条件数*。
添加“having”条件,只选择count(*)等于您需要满足的ModelB条件数的行
例子:

model_bs_to_find = [100, 200]
ModelA.all( :joins=>{:model_a_to_b=>:model_bs},
            :group=>"model_as.id",
            :select=>"model_as.*",
            :conditions=>["model_bs.id in (?)", model_bs_to_find],
            :having=>"count(*)=#{model_bs_to_find.size}")

注意:以这种方式指定的group和select参数将在mysql中工作,标准的sql方法是将model_的整个列表作为列放在group和select参数中。

10-01 07:17