mongodb查询:带$ gt的$ size返回0

时间:2014-10-02 11:37:24

标签: mongodb mongodb-query aggregation-framework

我想知道如何在mongodb查询中启用数组大小​​的不等式。

例如,我有以下两个查询:

> db.userStats.count({sessions:{$size:1}})
1381
> db.userStats.count({sessions:{$size:{$gt:0}}})
0

如果$gt按预期工作,则第二个查询的结果会有所不同,导致数字至少为1381.

第二个查询有什么问题,如何修复它以达到我想要的结果?

感谢

2 个答案:

答案 0 :(得分:4)

您不能像$size的文档中实际引用的那样执行此操作。因此,运算符单独评估“文字”结果,不能与“范围运算符”一起使用,例如您要求的。

您唯一真正的选择是通过使用$not运算符否定条件来要求“大小”“不等于0”。这完全有效:

db.userStats.count({ "sessions": { "$not": { "$size": 0 } } });

或者在聚合框架中使用$size的其他版本进行测试,只要您的MongoDB版本是2.6或更高版本:

db.userStats.aggregate([
    { "$group": {
         "_id": null,
         "count": {
             "$sum": {
                 "$cond": [
                     { "$gt": [ { "$size": "$sessions", 0 } ] },
                     1,
                     0
                 ]
             }
         }
    }}
])

可能还有$where形式的JavaScript评估:

db.userStats.count(function() { return this.sessions.length > 0 });

但可能比上一版本慢。

或者您实际上可以使用"dot notation"$exists运算符执行此操作:

db.userStats.count({ "sesssions.0": { "$exists": true } });

一般的想法是,如果索引0处有一个元素,那么该数组有一定的长度。

这一切都取决于你的方法,但这些形式中的任何一种都能得到正确的结果。

但是对于MongoDB的“最佳”性能,请不要使用任何这些方法。而是将数组“length”保留为您正在检查的文档的属性。这可以“索引”,并且发出的查询实际上可以访问该索引,而上述任何一个都无法做到。

保持这样:

db.userStats.update(
     { "_id": docId, "sessions": { "$ne": newItem } },
     {
         "$push": { "sessions": newItem },
         "$inc": { "countSessions": 1 }
     }
)

或删除:

db.userStats.update(
     { "_id": docId, "sessions": newItem  },
     {
         "$pull": { "sessions": newItem },
         "$inc": { "countSessions": -1 }
     }
)

然后你可以查询“countSesssions”,它也可以索引最佳性能:

db.userStats.find({ "countSessions": { "$gt": 0 } })

这是“最好”的方式。

答案 1 :(得分:2)

$ size不接受一系列值。见http://docs.mongodb.org/manual/reference/operator/query/size/

要为一系列值选择$ size,例如从1到3,您可以使用$或

db.userStats.count( { $or: [ {sessions:{$size:1}}, {sessions:{$size:2}}, {sessions:{$size:3}} ] } )

当然,$或者是一种有效但不是很好的解决方案。按照MongoDB的建议:

  

根据具有不同数量的字段选择文档   元素,创建一个在添加时递增的计数器字段   元素到一个领域。