2016-02-29 69 views
1

我有一个文档集合,每个文档都有一个字段,它是一个子文档数组,并且所有子文档都有一个公共字段'status'。我想查找所有子文档具有相同状态的所有文档。mongodb检查数组中的所有子文档是否在一个字段中具有相同的值

集合:

{ 
     "name" : "John", 
     "wives" : [ 
       { 
         "name" : "Mary", 
         "status" : "dead" 
       }, 
       { 
         "name" : "Anne", 
         "status" : "alive" 
       } 
     ] 
}, 
{ 
     "name" : "Bill", 
     "wives" : [ 
       { 
         "name" : "Mary", 
         "status" : "dead" 
       }, 
       { 
         "name" : "Anne", 
         "status" : "dead" 
       } 
     ] 
}, 
{ 
     "name" : "Mohammed", 
     "wives" : [ 
       { 
         "name" : "Jane", 
         "status" : "dead" 
       }, 
       { 
         "name" : "Sarah", 
         "status" : "dying" 
       } 
     ] 
} 

我要检查,如果所有的妻子死亡,发现只有比尔。

回答

1

您可以使用下面的聚集查询来获取他们的妻子都死了的人记录:

db.collection.aggregate(
    {$project: {name:1, wives:1, size:{$size:'$wives'}}}, 
    {$unwind:'$wives'}, 
    {$match:{'wives.status':'dead'}}, 
    {$group:{_id:'$_id',name:{$first:'$name'}, wives:{$push: '$wives'},size:{$first:'$size'},count:{$sum:1}}}, 
    {$project:{_id:1, wives:1, name:1, cmp_value:{$cmp:['$size','$count']}}}, 
    {$match:{cmp_value:0}} 
) 

输出:

{ "_id" : ObjectId("56d401de8b953f35aa92bfb8"), "name" : "Bill", "wives" : [ { "name" : "Mary", "status" : "dead" }, { "name" : "Anne", "status" : "dead" } ], "cmp_value" : 0 } 

如果你需要找到用户谁拥有的记录相同的状态,那么你可以删除最初的比赛阶段。

+0

看起来更容易有一个额外的字段来存储某种标志值(因为我只对一个状态字段值感兴趣)。不过谢谢。 –

+0

额外的标志将导致进一步的更新,并发现保持同步的标志 –

2

来处理这种情况的最有效方式是总是将是对“死”的状态中作为开幕查询“匹配”,否则你正在处理这不可能匹配的项目,以及逻辑真的很简单其次与$map$allElementsTrue

db.collection.aggregate([ 
    { "$match": { "wives.status": "dead" } }, 
    { "$redact": { 
     "$cond": { 
      "if": { 
       "$allElementsTrue": { 
        "$map": { 
         "input": "$wives", 
         "as": "wife", 
         "in": { "$eq": [ "$$wife.status", "dead" ] } 
        } 
       }    
      }, 
      "then": "$$KEEP", 
      "else": "$$PRUNE" 
     } 
    }}  
]) 

或者同样的事情$where

db.collection.find({ 
    "wives.status": "dead", 
    "$where": function() { 
     return this.wives.length 
      == this.wives.filter(function(el) { 
       el.status == "dead"; 
      }).length; 
    } 
}) 

两个基本测试“ST atus“价值的所有元素,以确保它们以最快的方式匹配。但只有$match$redact的总管道应该更快。而“少”流水线阶段(基本上每个通过数据)意味着更快。

当然,在文档上保留一个属性总是最快的,但它会涉及逻辑来设置只有在“所有元素”是相同属性的情况下。当然,通常意味着在每次更新之前通过从服务器加载文档来检查文档。

相关问题