node.jsarraysmongodbnode-mongodb-native

I want to get an array of documents of matching value for a field from same collection


Below is my collection:

[
    {
        "_id": {
            "$oid": "6427c43b0db930a08abc8f80"
        },
        "propertyType": "Flat",
        "entity": "1",
        "size": "28*32",
        "area": "896",
        "rate": "3570",
        "addedBy": "6427ae52533858bad362fc6f"
    },
    {
        "_id": {
            "$oid": "6427cda508bc3cc01c36fcf1"
        },
        "propertyType": "Banglow",
        "entity": "1",
        "size": "80*50",
        "area": "4000",
        "rate": "5600",
        "addedBy": "6427ae52533858bad362fc6f"
    },
    {
        "_id": {
            "$oid": "6427dbc3a39c42b59d95c364"
        },
        "propertyType": "Flat",
        "entity": "1",
        "size": "32*32",
        "area": "1024",
        "rate": "3500",
        "addedBy": "6427dd2aa39c42b59d95c368"
    },
    {
        "_id": {
            "$oid": "6427dbe1a39c42b59d95c365"
        },
        "propertyType": "Banglow",
        "entity": "6",
        "size": "43*100",
        "area": "4300",
        "rate": "6130",
        "addedBy": "6427ae52533858bad362fc6f"
    },
    {
        "_id": {
            "$oid": "6427dbc3a39c42b59d95c363"
        },
        "propertyType": "Banglow",
        "entity": "1",
        "size": "80*40",
        "area": "3200",
        "rate": "4820",
        "addedBy": "6427dd2aa39c42b59d95c368"
    }
]

I want below output :

[
    {
        "addedBy": "6427ae52533858bad362fc6f",
        "properties": {
            "flats": [
                {
                    "_id": {
                        "$oid": "6427c43b0db930a08abc8f80"
                    },
                    "propertyType": "Flat",
                    "entity": "1",
                    "size": "28*32",
                    "area": "896",
                    "rate": "3570",
                    "addedBy": "6427ae52533858bad362fc6f"
                }
            ],
            "banglows": [
                {
                    "_id": {
                        "$oid": "6427cda508bc3cc01c36fcf1"
                    },
                    "propertyType": "Banglow",
                    "entity": "1",
                    "size": "80*50",
                    "area": "4000",
                    "rate": "5600",
                    "addedBy": "6427ae52533858bad362fc6f"
                },
                {
                    "_id": {
                        "$oid": "6427dbe1a39c42b59d95c365"
                    },
                    "propertyType": "Banglow",
                    "entity": "6",
                    "size": "43*100",
                    "area": "4300",
                    "rate": "6130",
                    "addedBy": "6427ae52533858bad362fc6f"
                }
            ]
        }
    },
    {
        "addedBy": "6427dd2aa39c42b59d95c368",
        "properties": {
            "flats": [
                {
                    "_id": {
                        "$oid": "6427dbc3a39c42b59d95c364"
                    },
                    "propertyType": "Flat",
                    "entity": "1",
                    "size": "32*32",
                    "area": "1024",
                    "rate": "3500",
                    "addedBy": "6427dd2aa39c42b59d95c368"
                }
            ],
            "banglows": [
                {
                    "_id": {
                        "$oid": "6427dbc3a39c42b59d95c363"
                    },
                    "propertyType": "Banglow",
                    "entity": "1",
                    "size": "80*40",
                    "area": "3200",
                    "rate": "4820",
                    "addedBy": "6427dd2aa39c42b59d95c368"
                }
            ]
        }
    }
]

I want to have a list of all documents for same value of addedBy the documents grouped by propertyType. As to showcase a summary of type of properties addedBy each user. All the records are in same collection and I want output from that collection only.

I have tried below flow :

[
  {
    '$lookup': {
      'from': 'properties', 
      'localField': 'addedBy', 
      'foreignField': 'addedBy', 
      'as': 'user'
    }
  }, {
    '$project': {
      'user': 1, 
      '_id': 0
    }
  }
]

Solution

  • Essentially you want to group the documents of the collection, so each document will appear once on its relevant group (propertyType and addedBy). One option is to $group twice and use $arrayToObject:

    db.properties.aggregate([
      {$group: {
          _id: {addedBy: "$addedBy", properties: "$propertyType"},
          v: {$push: "$$ROOT"},
          k: {$first: "$propertyType"}
      }},
      {$group: {
          _id: "$_id.addedBy",
          properties: {$push: {k: "$k", v: "$v"}}
      }},
      {$project: {
          addedBy: "$_id", _id: 0,
          properties: {$arrayToObject: "$properties"}
      }}
    ])
    

    See how it works on the playground example