MongoDB对所有结果应用附加查询的迭代器

反正在mongo里面,通过MapReduce或Aggregation来应用基于第一个结果集的第二个查询,比如聚合中的聚合,或者MapReduce中的新发射/查询。

例如,我有物品的path模式(其中还包括parentId),我可以简单地通过以下方式获取所有的根:

db.collection.find({parentId: null} .toArray(function(err, docs) { }); 

我想要做的是确定这些文档是否有孩子,只是一个标志true/false 。 我可以遍历这些文档使用asynchronouseach和检查,但在大文档,这是不是非常高性能和导致事件循环延迟,我可以使用eachSeries ,但这只是缓慢。

理想情况下,我希望能够在Mongo内处理这一切。 任何build议,如果这是可能的?

编辑,示例集合:

 { _id: 1, parentId: null, name: 'A Root Node', path: '' } { _id: 2, parentId: 1, name: 'Child Node A', path: ',1' } { _id: 3, parentId: 2, name: 'Child Node B', path: ',1,2' } { _id: 4, parentId: null, name: 'Another Root Node', path: '' } 

这基本上代表了两个根节点,其中一个根节点( {_id: 1} )有两个孩子(一个是直接的),例如:

  • 1
    • 2
      • 3
  • 4

我想要做的是做一个基于parentId的查询,所以我可以通过使用null或通过parentId得到根节点我可以得到的孩子,并确定是否从这个结果集,任何项目包含儿童,例如{parentId: null}响应示例:

 [{ _id: 1, parentId: null, name: 'A Root Node', path '', hasChildren: true }, { _id: 4, parentId: null, name: 'Another Root Node', path '', hasChildren: false }] 

您可以尝试从物化path创build一个parentIds数组,然后可以在聚合pipe道中使用该数组来投影额外的字段/标志hasChildren

这可以通过对find()方法返回的游标使用map()方法来完成。 以下说明:

 var arr = db.collection.find({ "parentId": { "$ne": null } }) .map(function (e){ return e.path; }) .join('') .split(',') .filter(function (e){ return e; }) .map(function (e){ return parseInt(e); }), parentsIds = _.uniq(arr); /* using lodash uniq method to return a unique array */ 

使用这个parentIds数组,可以使用聚合框架,特别是使用set操作符 $setIsSubset$projectpipe道,该操作符使用两个数组,当第一个数组是第二个数组的子集时返回true,包括何时第一个数组等于第二个数组,否则返回false:

 db.collection.aggregate([ { "$match": { "parentId": null } }, { "$project": { "parentId": 1, "name": 1, "path": 1, "hasChildren": { "$setIsSubset": [ [ "$_id" ], parentIds ] } } } ], function (err, res) { console.log(res); });