Mongodb查询与相同文档中的字段

Rus*_*bot 31 mongodb

我有下一个json.

{
  "a1": {"a": "b"},
  "a2": {"a": "c"}
}
Run Code Online (Sandbox Code Playgroud)

我想要在同一文件中请求a1不等于a2的所有文件.

我怎么能这样做?

mne*_*syn 81

你可以使用$where:

db.myCollection.find( { $where: "this.a1.a != this.a2.a" } )
Run Code Online (Sandbox Code Playgroud)

但是,要注意这不会很快,因为它必须启动java脚本引擎并迭代每个文档并检查每个文档的条件.

如果你需要对大型集合进行此查询,或者经常,最好引入非规范化标志,例如areEqual.尽管如此,这种低选择性字段并不能产生良好的索引性能,因为候选集仍然很大.


Pau*_*aul 23

为了避免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}}
])
Run Code Online (Sandbox Code Playgroud)

在我们的开发服务器上,等效的JavaScript查询需要7倍的时间才能完成.

更新(2017年5月10日)

我刚刚意识到我的答案没有回答这个问题,这个问题想要不相等的价值(有时我真的很慢).这将适用于此:

db.myCollection.aggregate([
  {"$match":{"a1":{"$exists":true},"a2":{"$exists":true}}},
  {"$project": {
      "a1":1,
      "a2":1,
      "aEq": {"$eq":["$a1.a","$a2.a"]}
    }
  },
  {"$match":{"aEq": false}}
])
Run Code Online (Sandbox Code Playgroud)

$ne可以代替使用$eq,如果匹配条件改为true,但我觉得用$eqfalse更加直观.

  • 对于这种用例,我认为$ addFields会比$ project更好。 (2认同)

Moh*_*emy 12

更新

使用从mongo 3.6开始可用的新$ expr运算符,您可以在查询查询中使用聚合表达式,如下所示:

  db.myCollection.find({$expr: {$ne: ["$a1.a", "$a2.a"] } });
Run Code Online (Sandbox Code Playgroud)

虽然这个评论解决了这个问题,但我认为这个用例更好的匹配是使用$ 3.4版本的$ addFields运算符而不是$ project.

db.myCollection.aggregate([
     {"$match":{"a1":{"$exists":true},"a2":{"$exists":true}}},
     {"$addFields": {
           "aEq": {"$eq":["$a1.a","$a2.a"]}
         }
     },
     {"$match":{"aEq": false}} 
  ]);
Run Code Online (Sandbox Code Playgroud)


Cor*_*all 5

MongoDB在后台使用Javascript,因此

{"a": "b"} == {"a": "b"}
Run Code Online (Sandbox Code Playgroud)

会是false

所以要比较每个,您必须将其与a1.a == a2.a

要在MongoDB中做到这一点,您可以使用$ where运算符

db.myCollection.find({$where: "this.a1.a != this.a2.a"});
Run Code Online (Sandbox Code Playgroud)

假定每个嵌入文档将具有属性“ a”。如果不是这种情况,事情就会变得更加复杂。