Mongoid:基于嵌入式文档数组的大小查询

jsu*_*urf 5 ruby mongodb mongoid mongodb-query

这与此问题类似,但我无法弄清楚如何将其转换为Mongoid语法:

MongoDB查询基于嵌入文档的计数

让我说我有 Customer: {_id: ..., orders: [...]}

我希望能够找到所有拥有现有订单的客户,即orders.size> 0.我尝试过的查询Customer.where(:orders.size.gt => 0)无济于事.可以与exists?运营商合作吗?

Nei*_*unn 6

我更好的方法是使用MongoDB的本机语法,而不是像你所链接的问题的接受答案中指出的方法或JavaScript评估那样使用rails.特别是评估JavaScript条件会慢得多.

$exists对于长度大于零的数组的逻辑扩展是使用"点表示法"并测试"零索引"或数组的第一个元素的存在:

Customer.collection.find({ "orders.0" => { "$exists" => true } })
Run Code Online (Sandbox Code Playgroud)

这似乎可以使用任何索引值来完成,其中n-1等于您正在测试的数组的"长度"的索引值.

值得注意的是,对于"零长度"数组排除,$size运算符也是一种有效的替代方法,当用于$not否定匹配时:

Customer.collection.find({ "orders" => { "$not" => { "$size" => 0 } } })
Run Code Online (Sandbox Code Playgroud)

但这并不适用于较大的"大小"测试,因为您需要指定要排除的所有大小:

Customer.collection.find({ 
    "$and" => [ 
        { "orders" => { "$not" => { "$size" => 4 } } }, 
        { "orders" => { "$not" => { "$size" => 3 } } },
        { "orders" => { "$not" => { "$size" => 2 } } },
        { "orders" => { "$not" => { "$size" => 1 } } },
        { "orders" => { "$not" => { "$size" => 0 } } }
    ]
})
Run Code Online (Sandbox Code Playgroud)

所以其他语法更清晰:

Customer.collection.find({ "orders.4" => { "$exists" => true } })
Run Code Online (Sandbox Code Playgroud)

这意味着5个或更多成员以简洁的方式.

还请注意,这些条件都不能仅仅是一个索引,因此如果您有另一个过滤点,那么最好先包含该条件.


dai*_*no3 5

只需添加可能对某人有帮助的解决方案:

scope :with_orders, -> { where(orders: {"$exists" => true}, :orders.not => {"$size" => 0}}) }
Run Code Online (Sandbox Code Playgroud)