【发布时间】:2012-09-01 12:01:56
【问题描述】:
我有一种情况,我需要从 mongo 返回一个对象集合,但需要使用两个查询来获取结果。这些结果的顺序很重要,因为它们是分页的。
这是第一个查询:(基于类别和价格范围的列表)
my_listings = MoListing.where(criteria_a)
第二个查询需要使用第一个查询的结果作为过滤器。就像这样:
everything_else = MoListing.where(criteria_b)
然后联合结果:
my_listings << everything_else
最后,返回分页结果:
my_listings.page(1).per(25)
似乎我的部分问题是 mongo 查询在需要之前不会执行。有没有办法让我在给定点触发查询的执行?或者在构建这个结果集时我应该采取其他方法吗?
更新更多信息
我看到的行为是返回的只是listings 中的结果。我还确认everything_else 确实包含预期的记录(my_listings 中有 48 条记录,everything_else 中有 52 条记录)。
将.all 应用于我在 cmets 中提到的查询时,不会产生任何影响。 puts listings.inspect 导致
10:57:00 web.1 | #<Mongoid::Criteria
10:57:00 web.1 | selector: {"price"=>{"$gte"=>25, "$lte"=>75}},
10:57:00 web.1 | options: {},
10:57:00 web.1 | class: MoListing,
10:57:00 web.1 | embedded: false>
但是,listings.count 确实会导致 48。我只是错过了一些合并这些结果的愚蠢简单方法吗?一旦我在一个集合中得到结果,这将如何影响随后的分页功能。我正在使用kaminari 进行分页。
更新 2
根据下面的答案和我自己的反复试验,我发现 to_a 是一个解决方案,但不是一个理想的解决方案。这确实起作用:
#merge the results together as an Array
results = (listings.to_a | everything_else.to_a)
这导致通过 Kaminari 的分页必须更改,因为我们不再使用 mongo 标准,而是使用标准数组。这是新的分页方法:
Kaminari.paginate_array(results).page(page).per(per_page)
使用包含 100 条记录的小型数据集,这很好而且花花公子 - 54 毫秒
"debug":{"success":true,"pre_render_duration":54.808775999999995,"overall_duration":86.36554100000001,"count":25},"pagination":{"total_pages":4,"current_page":1}}
但是,使用 .to_a 方法来组合这些数据时,我发现使用更大的数据集时,时间明显变慢。虽然这些例子并不完全是一对苹果,但如此大的差异表明 to_a 返回所有内容的问题,迫使 Kaminari 处理更多的实际数据:
我没有 to_a 的结果,只返回应用了条件的所有记录 - 15 毫秒
"debug":{"success":true,"pre_render_duration":15.107164,"overall_duration":18.267599,"count":25},"pagination":{"total_pages":81,"current_page":1}}
我的结果与 to_a,合并两个结果集 - 415ms
"debug":{"success":true,"pre_render_duration":415.258199,"overall_duration":450.66537800000003,"count":25},"pagination":{"total_pages":81,"current_page":1}}
总而言之,这不是一个有效的选项。即使使用大型数据集,单独返回每个数据集也需要
在 SQL 中,我会做类似的事情
select
*
from
listings
where
field = "blah"
union all
select
*
from
listings
where
field <> "blah"
在 Mongo 中可以做到这一点吗?
【问题讨论】:
-
你的问题是什么意思?你得到不完整的结果吗?你只得到列表?是这样吗?请详细说明这里有什么问题?
-
在 Active Record 中触发执行的解决方案是使用 .all 函数。只需在查询后添加
.all,它们就会在那里自行执行,不会有延迟加载。
标签: ruby-on-rails ruby mongodb sinatra kaminari