mongodb查询:$ size和$ gt始终返回0

fst*_*tab 2 mongodb mongodb-query aggregation-framework

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

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

> db.userStats.count({sessions:{$size:1}})
1381
> db.userStats.count({sessions:{$size:{$gt:0}}})
0
Run Code Online (Sandbox Code Playgroud)

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

第二个查询出了什么问题,如何解决它以获得所需的结果?

谢谢

Nei*_*unn 6

您无法按照的文档中实际引用的方式进行操作$size。这样,操作员就只能评估“文字”结果,而不能与您要求的“范围运算符”结合使用。

您唯一的实际选择是通过与$not运算符取反条件来要求“不等于0”的“大小” 。这是完全有效的:

db.userStats.count({ "sessions": { "$not": { "$size": 0 } } });
Run Code Online (Sandbox Code Playgroud)

或者$size,只要您的MongoDB版本为2.6或更高,就可以使用聚合框架中的其他形式进行测试:

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

可能还采用$whereJavaScript评估的形式:

db.userStats.count(function() { return this.sessions.length > 0 });
Run Code Online (Sandbox Code Playgroud)

但是可能比上一个版本慢。

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

db.userStats.count({ "sesssions.0": { "$exists": true } });
Run Code Online (Sandbox Code Playgroud)

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

这完全取决于您的方法,但是这些形式中的任何一种都可以得到正确的结果。

但是为了获得MongoDB的“最佳”性能,请不要使用任何这些方法中的一种。而是将数组“ length”保留为要检查的文档的属性。您可以对它进行“索引”,并且发出的查询实际上可以访问该索引,而上述任何一项都不可以。

像这样维护它:

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

或删除:

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

然后,您可以查询“ countSesssions”,该索引也可以索引以获得最佳性能:

db.userStats.find({ "countSessions": { "$gt": 0 } })
Run Code Online (Sandbox Code Playgroud)

这是做到这一点的“最佳”方法。