2016-02-29 54 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的總管道應該更快。而「少」流水線階段(基本上每個通過數據)意味着更快。

當然,在文檔上保留一個屬性總是最快的,但它會涉及邏輯來設置只有在「所有元素」是相同屬性的情況下。當然,通常意味着在每次更新之前通過從服務器加載文檔來檢查文檔。

相關問題