我有下一个json.
{ "a1": {"a": "b"}, "a2": {"a": "c"} }
我想要在同一文件中请求a1不等于a2的所有文件.
我怎么能这样做?
你可以使用$where
:
db.myCollection.find( { $where: "this.a1.a != this.a2.a" } )
但是,要注意这不会很快,因为它必须启动java脚本引擎并迭代每个文档并检查每个文档的条件.
如果你需要对大型集合进行此查询,或者经常,最好引入非规范化标志,例如areEqual
.尽管如此,这种低选择性字段并不能产生良好的索引性能,因为候选集仍然很大.
为了避免JavaScript使用聚合框架:
db.myCollection.aggregate([ {"$match":{"a1":{"$exists":true},"a2":{"$exists":true}}}, {"$project": { "a1":1, "a2":1, "aCmp": {"$cmp":["$a1.a","$a2.a"]} } }, {"$match":{"aCmp":0}} ])
在我们的开发服务器上,等效的JavaScript查询需要7倍的时间才能完成.
我刚刚意识到我的答案没有回答这个问题,这个问题想要不相等的价值(有时我真的很慢).这将适用于此:
db.myCollection.aggregate([ {"$match":{"a1":{"$exists":true},"a2":{"$exists":true}}}, {"$project": { "a1":1, "a2":1, "aEq": {"$eq":["$a1.a","$a2.a"]} } }, {"$match":{"aEq": false}} ])
$ne
可以代替使用$eq
,如果匹配条件改为true
,但我觉得用$eq
用false
更加直观.
使用从mongo 3.6开始可用的新$ expr运算符,您可以在查询查询中使用聚合表达式,如下所示:
db.myCollection.find({$expr: {$ne: ["$a1.a", "$a2.a"] } });
虽然这个评论解决了这个问题,但我认为这个用例更好的匹配是使用$ 3.4版本的$ addFields运算符而不是$ project.
db.myCollection.aggregate([ {"$match":{"a1":{"$exists":true},"a2":{"$exists":true}}}, {"$addFields": { "aEq": {"$eq":["$a1.a","$a2.a"]} } }, {"$match":{"aEq": false}} ]);
MongoDB在后台使用Javascript,因此
{"a": "b"} == {"a": "b"}
会是false
。
所以要比较每个,您必须将其与a1.a == a2.a
要在MongoDB中做到这一点,您可以使用$ where运算符
db.myCollection.find({$where: "this.a1.a != this.a2.a"});
假定每个嵌入文档将具有属性“ a”。如果不是这种情况,事情就会变得更加复杂。