简体   繁体   中英

Find common attributes from nested array in MongoDB

Below is my schema:

  [{
    "attributes":[
        {
            "attrId":"123",
            "values":[
                    {"name": "asd"},
                    {"name": "bcc"}
                ]
        },
        {
            "attrId":"456",
            "values":[
                    {"name": "zzz"},
                    {"name": "bcc"}
                ]
        }
        ]
},

{
    "attributes":[
        {
            "attrId":"123",
            "values":[
                    {"name": "asd"},
                    {"name": "bcc"}
                ]
        },
        {
            "attrId":"456",
            "values":[
                    {"name": "kkk"},
                    {"name": "bcc"}
                ]
        }
        ]
}]

I want output as:

[{123:["asd","ccc"]}]

ie to return attrId and values if all values match with all other documents, I am thinking it to convert values into string like "asdbcc" so that it will be easy to compare.

You can try,

  • $group by null and make array of root objects and get count of total objects in root
  • $unwind deconstruct root array that we have created in above stage
  • $unwind deconstruct root.attributes array
  • $group by root.attributes.attrId and root.attributes.values and get total count of grouped documents and values to get k(key) as attrId and v(value) as array of values from values object using $map and get first totalCount field
  • $match expression using $expr check common document count and total root object document both are equal then return matching documents
  • $replaceRoot to replace and object after converting from $arraToObject of values array
db.collection.aggregate([
  {
    $group: {
      _id: null,
      root: { $push: "$$ROOT" },
      totalCount: { $sum: 1 }
    }
  },
  { $unwind: "$root" },
  { $unwind: "$root.attributes" },
  {
    $group: {
      _id: {
        attrId: "$root.attributes.attrId",
        values: "$root.attributes.values"
      },
      values: {
        $addToSet: {
          k: "$root.attributes.attrId",
          v: {
            $map: {
              input: "$root.attributes.values",
              in: "$$this.name"
            }
          }
        }
      },
      count: { $sum: 1 },
      totalCount: { $first: "$totalCount" }
    }
  },
  { $match: { $expr: { $eq: ["$count", "$totalCount"] } } },
  { $replaceRoot: { newRoot: { $arrayToObject: "$values" } } }
])

Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM