MongoDB:两个$或&s与一个隐含的AND - 预期行为相结合?

时间:2017-09-30 13:06:43

标签: mongodb mongodb-query

在MongoDB文档中说

db.inventory.find( {
  $and : [
      { $or : [ { price : 0.99 }, { price : 1.99 } ] },
      { $or : [ { sale : true }, { qty : { $lt : 20 } } ] }
  ]
})
  

此查询无法使用隐式AND操作构造,因为它多次使用$或运算符。

https://docs.mongodb.com/manual/reference/operator/query/and/

如果对两个OR使用隐式AND,您应该期待什么?行为是否定义明确?

从这个实验看,它看起来忽略了第一个OR谓词..

> db.mytest.insertMany([
{w: 0,  x: 0, y: 0, z: 0 },
{w: 0,  x: 0, y: 1, z: 0 },
{w: 0,  x: 0, y: 1, z: 1 },
{w: 0,  x: 1, y: 0, z: 0 },
{w: 0,  x: 1, y: 0, z: 1 },
{w: 0,  x: 1, y: 1, z: 0 },
{w: 0,  x: 1, y: 1, z: 1 },
{w: 1,  x: 0, y: 0, z: 0 },
{w: 1,  x: 0, y: 1, z: 0 },
{w: 1,  x: 0, y: 1, z: 1 },
{w: 1,  x: 1, y: 0, z: 0 },
{w: 1,  x: 1, y: 0, z: 1 },
{w: 1,  x: 1, y: 1, z: 0 },
{w: 1,  x: 1, y: 1, z: 1 },
])
...
>db.mytest.find({$or: [ {w: 1}, { x: 1} ],$or: [ {y: 1}, { z: 1} ]})
{ "_id" : ObjectId("59ce696828f7ac6a3372e64d"), "w" : 0, "x" : 0, "y" : 1, "z" : 0 }
{ "_id" : ObjectId("59ce696828f7ac6a3372e64e"), "w" : 0, "x" : 0, "y" : 1, "z" : 1 }
{ "_id" : ObjectId("59ce696828f7ac6a3372e650"), "w" : 0, "x" : 1, "y" : 0, "z" : 1 }
{ "_id" : ObjectId("59ce696828f7ac6a3372e651"), "w" : 0, "x" : 1, "y" : 1, "z" : 0 }
{ "_id" : ObjectId("59ce696828f7ac6a3372e652"), "w" : 0, "x" : 1, "y" : 1, "z" : 1 }
{ "_id" : ObjectId("59ce696828f7ac6a3372e654"), "w" : 1, "x" : 0, "y" : 1, "z" : 0 }
{ "_id" : ObjectId("59ce696828f7ac6a3372e655"), "w" : 1, "x" : 0, "y" : 1, "z" : 1 }
{ "_id" : ObjectId("59ce696828f7ac6a3372e657"), "w" : 1, "x" : 1, "y" : 0, "z" : 1 }
{ "_id" : ObjectId("59ce696828f7ac6a3372e658"), "w" : 1, "x" : 1, "y" : 1, "z" : 0 }
{ "_id" : ObjectId("59ce696828f7ac6a3372e659"), "w" : 1, "x" : 1, "y" : 1, "z" : 1 }
> 

我问这个问题,因为在我看来这种行为是不一致的。我错误地在我的代码中的几个地方使用了隐含的AND和OR。其中一个似乎给出了与使用和显式AND所期望的相同的答案。这是一个复杂的查询,所以我可能在查询或测试中犯了错误。很高兴知道这里发生了什么......可能还有另外一个我仍然需要清除的错误。

1 个答案:

答案 0 :(得分:3)

MongoDB处理

{$or: [ {w: 1}, { x: 1} ],$or: [ {y: 1}, { z: 1} ]}

as

{$or: [ {y: 1}, { z: 1} ]}

当MongoDB查询中的2个密钥相同时,最新的密钥会替换之前的密钥。

正如docs中所述,您需要在此明确$and