gpt4 book ai didi

ruby-on-rails - ruby rails : Concatenate results of Mongoid criterias and paging

转载 作者:可可西里 更新时间:2023-11-01 10:00:54 25 4
gpt4 key购买 nike

我很确定我做错了什么。考虑以下代码:

criteria1 = Model.where(...)
criteria2 = Model.where(...)
results = (criteria1.to_a + criteria2.to_a)[offset..(offset + count_per_page - 1)]

此代码连接两个不同标准的结果,并获得具有给定偏移量(分页)的一定数量的结果。

此代码中的问题是隐含的。 to_a 方法调用实际上将条件的所有结果作为数组加载到内存中

现在考虑一个非常大的集合……to_a 调用会显着降低所有速度。

我想做的是这样的:

criteria1 = Model.where(...)
criteria2 = Model.where(...)

# A criteria, which returns results of the first criteria concatenated with results of the second criteria
criteria = criteria1 + criteria2
results = criteria.offset(offset).limit(count_per_page)

重要的是第二个标准的结果第一个标准的结果之后。

有什么线索可以用 Mongoid 实现吗?

谢谢!

更新

Gergo Erdosi 建议使用merge 方法。我试过使用它,但它不是我要找的。这里的问题如下:

criteria1 = Model.where(:name => "John", :age => "23")
criteria2 = Model.where(:name => "Bob", :gender => "male")
criteria = criteria1.merge(criteria2)
p criteria.selector
# prints: { "name" => "Bob", :age => 23, :gender => "male" }

所以这里有两个问题:

  1. merge 不产生 OR,它用第二个查询覆盖第一个查询的公共(public)键;
  2. 即使我们使用 Model.or({ :name => "John"}, { :name => "Bob"})Model.in(:name => ["John", "Bob"]) 结果的顺序 不正确。我希望第一个标准的结果先出现,然后第二个标准的结果出现在之后

有可能我不明白某些事情,而 Gergo 的回答是正确的。你还有其他建议吗?谢谢。

更新 2

谢谢 Gergo 在这里帮助我。让我们在 Mongo shell 中尝试一个简单的例子:

// Fill out test db with some simple documents.
for (var i = 0; i < 10; ++i) { db.users.insert({ name: i % 2 ? "John" : "Bob", age: Math.round(Math.random() * 100) }); }

// These queries give me the same order of documents.
db.users.find({ name: { $in: ["Bob", "John"] } });
db.users.find({ $or: [{ name: "Bob" }, { name: "John" }] });

// Like this:
{ "_id" : ObjectId("53732076b110ab9be7619a8e"), "name" : "Bob", "age" : 69 }
{ "_id" : ObjectId("53732076b110ab9be7619a8f"), "name" : "John", "age" : 63 }
{ "_id" : ObjectId("53732076b110ab9be7619a90"), "name" : "Bob", "age" : 25 }
{ "_id" : ObjectId("53732076b110ab9be7619a91"), "name" : "John", "age" : 72 }
// ...

// But I wish to get concatenated results of these queries:
db.users.find({ name: "Bob" });
db.users.find({ name: "John" });

// Like this (results of the first criteria go first):
{ "_id" : ObjectId("53732076b110ab9be7619a8e"), "name" : "Bob", "age" : 69 }
{ "_id" : ObjectId("53732076b110ab9be7619a90"), "name" : "Bob", "age" : 25 }
// ...
{ "_id" : ObjectId("53732076b110ab9be7619a8f"), "name" : "John", "age" : 63 }
{ "_id" : ObjectId("53732076b110ab9be7619a91"), "name" : "John", "age" : 72 }
// ...

请注意,我不能在这里使用简单的排序,因为实际应用中的数据更加复杂。在实际应用中,标准如下所示:

// query variable is a string
exact_match_results = Model.where(:name => query)
inexact_match_results = Model.where(:name => /#{query}/i)

所以我们不能在这里只按字母顺序排序。

最佳答案

使用merge方法:

criteria = criteria1.merge(criteria2)
results = criteria.offset(offset).limit(count_per_page)

您可以在 method description 中查看详细信息.

编辑:如前所述,merge 不会产生 OR 查询。

irb(main):010:0> Model.where(name: 'John').merge(Model.where(name: 'Bob'))
=> #<Mongoid::Criteria
selector: {"name"=>"Bob"}
options: {}
class: Model
embedded: false>

在这种情况下,这不是预期的行为。原因是 merge 使用了 Hash.merge,它的行为是这样的。 relevant来自 Criteria.merge 的代码:

selector.merge!(criteria.selector)

这可以说明为:

irb(main):011:0> {name: 'John'}.merge({name: 'Bob'})
=> {:name=>"Bob"}

正因为如此,就如何以结果为 OR 查询的方式合并两个条件给出一般性建议并不容易。但只要稍微改变一下标准,就有可能。例如:

criteria1 = Model.any_of(name: 'John').where(age: '23')
criteria2 = Model.any_of(name: 'Bob').where(gender: 'male')

合并的结果是包含两个名称的 OR 查询:

irb(main):014:0> criteria1.merge(criteria2)
=> #<Mongoid::Criteria
selector: {"$or"=>[{"name"=>"John"}, {"name"=>"Bob"}], "age"=>"23", "gender"=>"male"}
options: {}
class: Model
embedded: false>

关于ruby-on-rails - ruby rails : Concatenate results of Mongoid criterias and paging,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23638357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com