skip to Main Content

I’m using MongoDb with Node.js. And I’m having trouble with aggregation.This is the Example of data in Collection in Database:

{
 "name": "abcdef",
 "address": ghijk,
 "reli":"A",
 "prov:"a" ,
}

{
"name": "xyz",
 "address": "vwz",
 "reli":"B",
 "prov:"b" ,
}

{
"name": "qwe",
 "address": "rty",
 "reli":'C',
 "prov:"c" ,
},
 {
 "name": "abcdef",
 "address": ghijk,
 "reli":"A",
 "prov:"a" ,
}
{
"name": "hat",
 "address": "ate",
 "reli":'C',
 "prov:"c" ,
},

This is my query to count:

const count = await db.aggregate([
    {
      $facet: {
        "reli": [
          { $group: { _id: '$reli', count: { $sum: 1 } } }
        ],
        "prov": [
          { $group: { _id: '$prov', count: { $sum: 1 } } }
        ],

This is my result of the query:

  [
    {
        "reli": [
            {
                "_id": "A",
                "count": 2
            },
            {
                "_id": "B",
                "count": 1
            },
            {
            "_id": "C",
            "count": 2
             }
    "prov": [
            {
                "_id": "a",
                "count": 2
            },
            {
                "_id": "b",
                "count": 1
            },
            {
            "_id": "c",
            "count": 2
             }

}]

I want to aggregate this data. And only want values for every reli and prov and it’s count in my results.

Expecting Output:

    [
    
    "reli":{
    
    A:2  // As my Collection has 2 "A" And 2 is it's count
    C:2  // As there is 2 "C" in Collection.

    }

    "prov":{
    c:2 //As there are 2 "c" in Collection. 
    b:1 //As there are 1 "b" in Collection
     }
]

2

Answers


  1. You can use $arrayToObject to get what you want here, creating keys from your values. For example:

    db.collection.aggregate([
      {
        $facet: {
          reli: [
            {$group: { _id: "$reli", v: {$sum: 1}}},
            {$project: {v: 1, k: "$_id", _id: 0}}
          ],
          prov: [
            {$group: {_id: "$prov", v: {$sum: 1}}},
            {$project: {v: 1, k: "$_id", _id: 0}}
          ]
        }
      },
      {
        $project: {
          prov: {$arrayToObject: "$prov"},
          reli: {$arrayToObject: "$reli"}
        }
      }
    ])
    

    Playground example

    If there is a correlation between the reli and prov group, as in your example, you can avoid the $facet, group once, count once and only project twice.

    Login or Signup to reply.
  2. You may try to use $group like this, the output isn’t exactly like expected, but it may help you :

    const reli = await db.collection.aggregate([
      {
        '$group': {
          '_id': '$reli', 
          'count': {
            '$sum': 1
          }
        }
      }, {
        '$project': {
          '_id': 0, 
          'reli': '$_id', 
          'count': 1
        }
      }
    ])
    
    const prov = await db.collection.aggregate([
      {
        '$group': {
          '_id': '$prov', 
          'count': {
            '$sum': 1
          }
        }
      }, {
        '$project': {
          '_id': 0, 
          'prov': '$_id', 
          'count': 1
        }
      }
    ])
    
    const res = {
      reli,
      prov
    };
    

    output :

    {
      "prov": [
        { "count": 2, "prov": "a" },
        { "count": 1, "prov": "b" },
        { "count": 2, "prov": "c" }
      ],
      "reli": [
        { "count": 2, "reli": "A" },
        { "count": 2, "reli": "C" },
        { "count": 1, "reli": "B" }
      ]
    }
    

    From this data, if you need it, you could re write key:value, for exact data model as you asked.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search