查找某些字段与MongoDB和Node.js中的对象具有完全相同元素的文档

我有一个像这样的ID数组:

[5, 7, 9, 4, 18] 

我有一个与以下格式插入文档的集合:

 db.collection('groups').insert( [ { members: [ {member: 5, hasSeen: false, requiresAction: true}, {member: 7, hasSeen: true, requiresAction: true}, {member: 4, hasSeen: false, requiresAction: false} ] }, { members: [ {member: 5, hasSeen: false, requiresAction: true}, {member: 4, hasSeen: false, requiresAction: false}, {member: 7, hasSeen: true, requiresAction: true}, {member: 9, hasSeen: false, requiresAction: false}, {member: 18, hasSeen: false, requiresAction: false} ] }, { members: [ {member: 7, hasSeen: true, requiresAction: true}, {member: 9, hasSeen: false, requiresAction: false}, {member: 4, hasSeen: false, requiresAction: false}, {member: 18, hasSeen: false, requiresAction: false}, {member: 1, hasSeen: false, requiresAction: false}, {member: 5, hasSeen: false, requiresAction: true} ] } ] ); 

我想查找集合“组”中的所有文档,其中包含上述数组中的“成员”标识,顺序应该没有关系。 例如,如果使用上述数组进行search,则只有第二个插入的文档将从上面返回。

您需要使用MongoDB的聚合pipe道来查找所需的文档。

下面列出了在聚合中采用的步骤:

  1. 通过解构members数组来反规范化每个文档。

    这可以通过使用$ unwind聚合运算符来实现:

    从input文档中解构一个数组字段,为每个元素输出一个文档。 每个输出文档都是由元素replace的数组字段值的input文档。

    $unwind操作符会将每个文档分成几个文档,每个新文档包含一个具有单个成员对象的members字段:

     {_id: 'first_id', members: {member: 4, hasSeen: false}} {_id: 'first_id', members: {member: 5, hasSeen: fasee}} 

    要使用$unwind运算符,我们只需将其添加到聚合pipe道:

     {$unwind: "$members"} 
  2. 通过_id字段对文档进行分组,将成员标识添加到数组中

    这可以通过使用$ group聚合运算符来实现:

    按照某个指定的expression式对文档进行分组,并将每个不同分组的文档输出到下一个阶段。 输出文档包含一个_id字段,其中包含按键的不同组。 输出文档还可以包含计算字段,该字段包含由$ group的_id字段分组的一些累加器expression式的值。

    $group操作符将允许我们通过它们的id将非规范化文档分组,所以我们将获得这种forms的文档:

     {_id: 'first_id', member_ids: [5, 7, 4] } 

    将文档分组和汇总ID所需的expression式是:

     {$group: { _id: "$_id", member_ids: { $push: "$members.member" } }} 
  3. 根据定义的标准过滤结果文档

    这可以通过使用$ match聚合运算符来实现:

    过滤文档以仅将符合指定条件的文档传递到下一个stream水线阶段。

    要获取其member_ids属性与条件匹配的文档,expression式为:

     {$match: {'member_ids': { $all: [5, 7, 9, 4, 18] } } } 

最后的聚合查询将是:

 db.collection('groups').aggregate( [ {$unwind: "$members"}, {$group: { _id: "$_id", member_ids: { $push: "$members.member" } }}, {$match: {'member_ids': { $all: [5, 7, 9, 4, 18] } } } ] );