2015-05-05 221 views
2

使用貓鼬用MongoDB中,我的模式如下:失蹤兒童

​​

而且數據如下所示:

[{"partcode":"A1","children":["B1","B2","B3","B4"]}, 
{"partcode":"B1","children":["C11","C21","C31","C41"]}, 
{"partcode":"B3","children":["C13","C23","C33","C43"]}, 

我可以用下面的靜態查詢A1的兒童場撥打:

PartSchema.static('getChildren', function (partcode, callback) { 
    var self = this; 
    self.findOne({ partcode: partcode }, childrenOnly) 
     .exec(function (err, doc) { 
     return self.find({"partcode": {"$in": doc.children} }, exclId, callback); 
    }); 
}); 

這將返回(通過快遞)

[{"partcode":"B1","children":["C11","C21","C31","C41"]}, 
{"partcode":"B3","children":["C13","C23","C33","C43"]}] 

我需要的是返回所有的孩子沒找到,例如:

[{"children":["B2","B4"}] 
+1

標題爲「失蹤兒童」賽後.....的xD – aludvigsen

回答

1

你可以使用_.difference()方法從lodash庫來計算陣列設置差異:

var _ = require("lodash"); 
PartSchema.static('getChildren', function (partcode, callback) { 
    var self = this; 
    self.findOne({ partcode: partcode }, childrenOnly) 
     .exec(function (err, doc) { 
     var promise = self.find({"partcode": {"$in": doc.children} }, exclId).lean().exec(); 
     promise.then(function (res){ 
      var codes = res.map(function (m) { 
       return m.children; 
      }), 
       obj = {"children": _.difference(doc.children, codes)}, 
       result = []; 
      result.push(obj); 
      return result; 
     }); 
    }); 
}); 

- UPDATE -

隨着MongoDB的aggregation framework,你可以達到預期的效果。我們首先在mongoshell中演示這個。

假設你插入的部分收集了下面的測試文件:

db.part.insert([ 
    {"partcode":"A1","children":["B1","B2","B3","B4"]}, 
    {"partcode":"B1","children":["C11","C21","C31","C41"]}, 
    {"partcode":"B3","children":["C13","C23","C33","C43"]} 
]) 

這裏給你有孩子partcodes對於給定partcode的陣列中的聚集可能是有用的,說"A1",這是["B1","B2","B3","B4"] 。在這種情況下,您的聚集管道將包括以下聚集流水線階段:

  1. $match - 需要使用此過濾他們的孩子partcodes不是["B1","B2","B3","B4"]陣列中的這些文件。這是使用$nin運營商實現的。

  2. $group - 將來自上一個流的所有文檔分組,並創建具有父級代碼的附加數組字段。通過使用蓄電池運營商$addToSet可能。

  3. $project - 通過添加新的字段partcode(其最終將成爲結果對象的一部分),並且抑制_id字段重塑流中的每個文檔。這是您可以使用集合運算符獲得標準中的父部件代碼與不在管道文檔中的父部件代碼之間的數組差異的地方。

你最終匯聚運營商應該是這樣的(使用mongoshell):

var children = ["B1","B2","B3","B4"]; 
db.part.aggregate([   
    { 
     "$match": { 
      "children": { "$nin": children } 
     } 
    }, 
    { 
     "$group": { 
      "_id": null, 
      "parents": { 
       "$addToSet": "$partcode" 
      } 
     } 
    }, 
    { 
     "$project": { 
      "_id": 0, 
      "partcode": { 
       "$setDifference": [ children, "$parents" ] 
      } 
     } 
    } 
]).pretty() 

輸出

/* 0 */ 
{ 
    "result" : [ 
     { 
      "partcode" : ["B2","B4"] 
     } 
    ], 
    "ok" : 1 
} 

在你的貓鼬的架構方法,使用相同的概念:

PartSchema.static('getChildren', function (partcode, callback) { 
    var self = this; 
    self.findOne({ partcode: partcode }, childrenOnly) 
     .exec(function (err, doc) { 
      var pipeline = [   
       { 
        "$match": { 
         "children": { "$nin": doc.children } 
        } 
       }, 
       { 
        "$group": { 
         "_id": null, 
         "parents": { 
          "$addToSet": "$partcode" 
         } 
        } 
       }, 
       { 
        "$project": { 
         "_id": 0, 
         "partcode": { 
          "$setDifference": [ doc.children, "$parents" ] 
         } 
        } 
       } 
      ], 
      self.aggregate(pipeline).exec(callback);     
    }); 
}); 

或者用貓鼬aggregation pipeline builder了一口流利的電話:

PartSchema.static('getMissedChildren', function (partcode, callback) { 
    var self = this; 
    self.findOne({ partcode: partcode }, childrenOnly) 
     .exec(function (err, doc) { 
      var promise = self.aggregate() 
       .match({"children": { "$nin": doc.children }}) 
       .group({"_id": null,"parents": {"$addToSet": "$partcode"}}) 
       .project({"_id": 0,"partcode": {"$setDifference": [ doc.children, "$parents" ]}}) 
       .exec(callback); 
      }); 
    }); 
+0

Chridam嗨 - 這差不多吧。 'result'的'console.log'顯示[[「children」:[「B2」,「B4」}]',但原始調用顯示一個貓鼬對象(無疑嵌入了數據)。 – Terry

+0

我認爲express期望'MongooseDocument'格式,所以需要相反,因爲'result'是JSON,應該是MongooseDocument。 – Terry

+0

這將是太棒了 - 謝謝。 – Terry