Javascript MongoDB:如何将数组的$size与另一个文档项进行比较?
MongoDB:如何在mongo控制台和通过JavaScript Node.js执行类似操作:Javascript MongoDB:如何将数组的$size与另一个文档项进行比较?,javascript,node.js,mongodb,mongodb-query,aggregation-framework,Javascript,Node.js,Mongodb,Mongodb Query,Aggregation Framework,MongoDB:如何在mongo控制台和通过JavaScript Node.js执行类似操作: db.turnys.find( { users:{$size:seats } } ) turnydb.turnys看起来像这样: [ { "gId": "5335e4a7b8cf51bcd054b423", "seats": 2, "start": "2014-03-30T14:23:29.688Z", "end": "2014-03-30T14:25:29.68
db.turnys.find( { users:{$size:seats } } )
turnydb.turnys看起来像这样:
[
{
"gId": "5335e4a7b8cf51bcd054b423",
"seats": 2,
"start": "2014-03-30T14:23:29.688Z",
"end": "2014-03-30T14:25:29.688Z",
"rMin": 800,
"rMax": 900,
"users": [],
"_id": "533828e1d1a483b7fd8a707a"
},
{
"gId": "5335e4a7b8cf51bcd054b423",
"seats": 2,
"start": "2014-03-30T14:23:29.688Z",
"end": "2014-03-30T14:25:29.688Z",
"rMin": 900,
"rMax": 1000,
"users": [],
"_id": "533828e1d1a483b7fd8a707b"
},
...
]
您可以使用
$where
查询:
db.turnys.find({ $where: "this.users.length == this.seats" })
您可以将运算符与包含JS表达式的字符串一起使用,也可以直接使用JavaScript函数:
> db.turnys.find(function() { return this.users.length == this.seats })
虽然您可以按照其他人的建议使用
$where
,以便进行跨域比较,但如果可能,我不建议您:
没有索引可用于此搜索。Mongo将扫描每个文档,并针对每个文档执行一个JavaScript表达式以进行跨字段比较。这将是一个昂贵且缓慢的操作
在MongoDB的下一个版本(2.6)中,您将能够在可以比较两个字段的聚合中使用$size
但是,为了获得最佳性能,我建议您存储一个具体化的布尔值,用于存储users
数组中的元素数是否等于seats
中存储的元素数。如果不想获取整个数组以获取计数并与字段“seats”进行比较,可以使用$inc
(正数和负数)轻松存储当前用户数
如果您必须使用,我建议您尝试进行一些筛选,如果可能的话,这可能有助于避免全表扫描。可能是日期范围,或者检查
用户
数组是否为空,等等。您可以使用以下任一方法
db.flight.find({"$where":"function() { return this.users.length == this.seats}" })
或
或
所有这些都可以满足您的目的,但问题是效率,除非严格必要,否则不应使用“$where”查询:它们比常规查询慢得多,因此请尝试避免使用“$where”查询。在接受以任何方式使用运算符方面存在实际问题。特别是考虑到你提出的一些“以后”的问题。您需要阅读该操作员的手册页面(如链接中所示) 短点:
- 操作员调用完全收集扫描,以便进行比较。这在“现实世界”案例中是坏消息,因为没有办法以任何方式“限制”此搜索使用索引,从而减少工作集
- 本质上,该操作符调用“任意JavaScript执行”。这意味着两件事1)每个文档必须在每次比较时从其本机BSON形式扩展为“JavaScript”对象形式(成本)2)您正在为每个和每个比较调用一个“JavaScript”解释器,即而不是本机代码
$inc
,在文档中保留了total_users
字段
db.collection.aggregate([
{“$project”:{
“gId”:1,
“alloc”:{“$eq”:[“$total_users”,“$seats”]}
}},
{“$match”:{“alloc”:1}
])
基本上,您可以在文档中选择所需的所有字段,只要您通过简单地执行“逻辑”比较(如运算符所示)来进行“alloc”字段所示的比较即可
在未来的版本中(在编写本文时很快),您甚至可以在“聚合”操作中找到数组的名称。因此,“而不是”在“数组”成员上保留计数器,您可以这样做:
db.collection.aggregate([
{“$project”:{
“gId”:1,
“alloc”:{“$eq”:[{“$size”:“$users”},“$seats”]}
}},
{“$match”:{“alloc”:1}
])
但这自然会带来“成本”,因此最好的选择还是根据您的需要在文档上保留“计数器”
虽然这里的两种方法都*仍然**导致“收集扫描”(在此上下文中,因为存在无其他$match条件),但最终结果将比其他答案中显示的“JavaScript”执行速度快很多倍
使用“本机代码”方法作为最佳实践解决方案。我想对这个伟大的答案也给出+1,但我还没有足够的声誉去投票。到时候我会投赞成票的。谢谢你能告诉我同样的事情吗?我怎么能为不平等做。对于我的数据库,我尝试了两种方法,但都不起作用。我有两个数组而不是一个数组。1.db.us_election_nodes_with_tweet.find({$and:[{result:{{ne:{size:{tweets},{$size:$tweetIds}]},{result:{$exists:true}}]})。pretty()和aslo 2。db.us_election_nodes_with_tweets.aggregate([{“$project”:{“\u id”:1,“alloc”:{“$ne”:[{“$size”:“$tweets”},{“$size”:“$tweets”},{“$size”:“$tweetIds”}},{“$match”:{“alloc”:1}])我想给它一个+1,但还没有名声。等我回来再做。谢谢
db.turnys.find({ $where: "this.users.length == this.seats" })
db.turnys.find(function() { return this.users.length == this.seats })