2014-10-09 24 views
0

说我有一个文档的集合,象下面这样:当属性不​​存在时选择记录?

{ 
    title: "test1", 
    items: 
    [ 
     {id: 1, sub_id: 23, value:"some value"}, 
     {id: 2, value:"some value"} 
    ] 
}, 
{ 
    title: "test2", 
    items: 
    [ 
     {id: 4, sub_id: 34, value:"blah"}, 
     {id: 5, sub_id: 56, value:"whatever"}, 
    ] 
} 

我想选择其中属性sub_id不存在与id属性确实存在。如果我运行查询:

db.myCollection.find({"items.sub_id": {$exists: false}}) 

返回我想要的记录(用test1标题的文件),但是当我运行此查询:

db.myCollection.find({"items.sub_id": {$exists: false}, "items.id": {$exists:true}}) 

它没有返回。我的第二个查询不应该返回与第一个查询相同的结果

回答

1

实际上,您的第一个查询无法返回您给出的样本的结果。原因是这两个文档都没有没有数组元素不包含“sub_id”属性。因此,在第一个文档中,虽然第二个数组元素缺少该属性,但第一个文档确实有一个,因此该条件实际上是错误的。一个有趣的事情与$exists和一个虚假的测试位。

所以为了使这项工作,你需要比较个别数组元素的条件。这意味着你需要的$elemMatch操作:

db.myCollection.find({ 
    "items": { 
     "$elemMatch": { 
      "id": { "$exists": true }, 
      "sub_id": { "$exists": false } 
     } 
    } 
}) 

这正确选择具有地方有一个“id”属性,但没有“sub_id”属性的数组元素的文档。

由于是$exists遍历文件相匹配的条件下,同样也适用于一个单一的元素,以及,因此您使用$elemMatch只有单场情形之一的方式:

db.myCollection.find({ 
    "items": { 
     "$elemMatch": { 
      "sub_id": { "$exists": false } 
     } 
    } 
}) 

因此,强制测试应用于数组元素,当然一个元素没有属性,因此至少有一个匹配并返回文档。