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

时间:2016-03-30 20:50:41

标签: javascript node.js mongodb express

我有一系列像这样的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}
      ]
    }
  ]
);

我想在上面的数组中找到包含“成员”ID的集合“组”中的所有文档,并且的顺序不应该。例如,如果使用上述数组进行搜索,则将从上方返回第二个插入的文档。

1 个答案:

答案 0 :(得分:1)

您需要使用MongoDB's aggregation pipeline来查找所需的文档。

汇总中采用的步骤如下:

  1. 通过解构members数组来对每个文档进行非规范化。

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

      

    从输入文档解构数组字段,为每个元素输出文档。每个输出文档都是输入文档,数组字段的值由元素替换。

    $unwind运算符会将每个文档拆分为多个文档,每个新文档都包含一个members字段,该字段包含一个成员对象:

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

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

    {$unwind: "$members"}
    
  2. 按照_id字段对文档进行分组,将成员ID添加到数组

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

      

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

    $group运算符允许我们在累积成员ID时通过其ID对非规范化文档进行分组,以便我们获取此表单的文档:

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

    对文档进行分组并累积ID所需的表达式为:

    {$group: { _id: "$_id", member_ids: { $push: "$members.member" } }}
    
  3. 根据定义的条件过滤生成的文档

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

      

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

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

    {$match: {'member_ids': { $all: [5, 7, 9, 4, 18] } } }
    
  4. 最终的聚合查询将是:

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