这与此问题类似,但我无法弄清楚如何将其转换为Mongoid语法:
MongoDB query based on count of embedded document
假设我有Customer: {_id: ..., orders: [...]}
我希望能够找到所有拥有现有订单的客户,即orders.size>我试过像Customer.where(:orders.size.gt => 0)
这样的查询无济于事。是否可以使用exists?
运算符完成?
答案 0 :(得分:7)
我更好的方法是使用MongoDB的本机语法,而不是像你所链接的问题的接受答案中指出的方法或JavaScript评估那样使用rails。特别是评估JavaScript条件会慢得多。
对于长度大于零的数组,$exists
的逻辑扩展名是使用"dot notation"并测试是否存在“零索引”或数组的第一个元素:
Customer.collection.find({ "orders.0" => { "$exists" => true } })
似乎可以使用任何索引值来完成,其中n-1
等于您正在测试的数组的“长度”的索引值。
值得注意的是,对于“零长度”数组排除,当$size
与$not
一起使用时,{{3}}运算符也是一种有效的替代方法:
Customer.collection.find({ "orders" => { "$not" => { "$size" => 0 } } })
但这并不适用于较大的“尺寸”测试,因为您需要指定要排除的所有尺寸:
Customer.collection.find({
"$and" => [
{ "orders" => { "$not" => { "$size" => 4 } } },
{ "orders" => { "$not" => { "$size" => 3 } } },
{ "orders" => { "$not" => { "$size" => 2 } } },
{ "orders" => { "$not" => { "$size" => 1 } } },
{ "orders" => { "$not" => { "$size" => 0 } } }
]
})
所以其他语法更清晰:
Customer.collection.find({ "orders.4" => { "$exists" => true } })
这意味着5个或更多成员的简洁方式。
请注意,这些条件都不能只是一个索引,所以如果你有另一个过滤点,最好先包含那个条件。
答案 1 :(得分:5)
只需添加可能对某人有帮助的解决方案:
scope :with_orders, -> { where(orders: {"$exists" => true}, :orders.not => {"$size" => 0}}) }