在MongoDB中,如何根据子集合大小查找项目?

在MongoDB中,如何根据子集合大小查找项目?,mongodb,find,size,where,Mongodb,Find,Size,Where,假设我有: > db.users.save({name: 'John', orders:[{price: 10, date: new Date('Feb 2, 2013')}, {price: 5, date: new Date('Feb 14, 2013')}]}); > db.users.save({name: 'Tim', orders:[{price: 15, date: new Date('Jan 27, 2013')}, {price: 5, date: new Date

假设我有:

> db.users.save({name: 'John', orders:[{price: 10, date: new Date('Feb 2, 2013')}, {price: 5, date: new Date('Feb 14, 2013')}]});
> db.users.save({name: 'Tim', orders:[{price: 15, date: new Date('Jan 27, 2013')}, {price: 5, date: new Date('Feb 8, 2013')}]});
找到“2013年2月至少有2份订单的所有用户”的最佳做法是什么

我假设我可以使用$where操作符并构建一个JS函数来完成这项工作,但我担心它会成为我应用程序的性能杀手

我还可以为我的用户计算一个新字段:Feb2013OrdersCnt,该字段将在每次添加订单时更新,但我希望更改查询中的日期范围(例如,在2013-02-01和2013-02-09之间>2个订单)。
有什么有效的方法可以做到这一点吗

我想说您可以使用
$size
操作符(),但是您需要一个带时间括号的数组元素计数,这意味着其中一些元素在查找时不会出现

一种方法可以是使用聚合框架:

db.users.aggregate([
    {$unwind: '$orders'},
    {$match: {'orders.date': {$gte: new Date('01-02-2013'), $lt: new Date('01-03-2013') }}},
    {$group: {_id: '$name', sum_orders: {$sum: 1}}},
    {$match: {sum_orders: {$gte: 2}}}
])
这大概可以转化为:2013年2月至少有2份订单的所有用户

希望有帮助

编辑
出于性能原因,最好在
$unwind
之前添加一个日期匹配项,以忽略那些没有您想要的订单范围的客户。

我想说的是,您可以使用
$size
操作符()但是,您需要一个时间括号内的数组元素计数,这意味着其中一些元素在您查找的时间内不会出现

一种方法可以是使用聚合框架:

db.users.aggregate([
    {$unwind: '$orders'},
    {$match: {'orders.date': {$gte: new Date('01-02-2013'), $lt: new Date('01-03-2013') }}},
    {$group: {_id: '$name', sum_orders: {$sum: 1}}},
    {$match: {sum_orders: {$gte: 2}}}
])
这大概可以转化为:2013年2月至少有2份订单的所有用户

希望有帮助

编辑
出于性能原因,最好在
$unwind
之前添加一个日期匹配项,以忽略在您寻找的范围内没有订单的客户。

match
unwind
之前可能会执行得更好,但您必须小心编写
match
子句。这篇博文解释了这些问题。@SriSankaran确实在数组中的任何东西上都匹配mongodb,这就是使用elemMatch的原因,但是这里的想法是限制输入到下一个管道中的根文档的数量,这样您就不会解卷不需要的文档,因此,子文档值不符合时间范围的任何文档都应该被忽略。感谢您的回答,我将与聚合框架进行检查,并在
展开之前向您发布
匹配
,这样做可能会更好,但是您必须小心编写
匹配
子句。这篇博文解释了这些问题。@SriSankaran确实在数组中的任何东西上都匹配mongodb,这就是使用elemMatch的原因,但是这里的想法是限制输入到下一个管道中的根文档的数量,这样您就不会解卷不需要的文档,因此,任何子文档值不符合时间范围的文档都应该被忽略。感谢您的回答,我将与聚合框架进行检查,我将随时向您发布