consider all fields when grouping in mongodb

Asked

Viewed 264 times

0

I have the following array:

[
  {
    “user”: “USER1”,
    “last”: “USER1”
  },
  {
    “user”: “USER1”,
    “last”: “USER2”
  },
  {
    “user”: “USER2”,
    “last”: “USER1”
  },
  {
    “user”: “USER2”,
    “last”: “USER2”
  },
  {
    “user”: “USER1”,
    “last”: “USER2”
  },
  {
    “user”: “USER1”,
    “last”: null
  }
]

I’m performing the following consultation on mongodb:

{$group: {
  _id: “$user”,
  total: {$sum: 1},
  last: {$sum: {$cond: [
    {$eq: ['$last’, '$user']}, 1, 0
  ]}}
}}

I expect this result:

[
  {
    _id: “USER1”
    total: 4,
    last: 2
  },
{
    _id: “USER2”
    total: 2,
    last: 3
  }
]

But I’m getting this:

[
  {
    _id: “USER1”
    total: 4,
    last: 1
  },
  {
    _id: “USER2”
    total: 2,
    last: 1
  }
]

I know the problem is in grouping, it only finds the last if the current user is the same.

How I can group, but at the time of counting consider all values?

1 answer

1


I’m gonna take you one step at a time to get it all in one piece!

//Primeiro vamos extrair somente as informações que queremos para nossa busca, no caso os users diferentes
db.teste.aggregate([
  {$group:{
    _id: "$user"
  }}
])

//Aqui vamos pegar os indices da busca reinserir no nosso filtro
db.teste.aggregate([
  {$group:{
    _id: "$user"
  }},
  {$lookup:{
    from: "teste",
    let: { indice: "$_id" },
    pipeline: [],
    as: "res"
  }}
])

//Vamos contrar o total de elementos reinseridos
db.teste.aggregate([
  {$group:{
    _id: "$user"
  }},
  {$lookup:{
    from: "teste",
    let: { indice: "$_id" },
    pipeline: [
      {$group:{
        _id: null,
        total:{$sum:1}
      }}
    ],
    as: "res"
  }}
])

//Agora vamos testar uma cond verdadeira
db.teste.aggregate([
  {$group:{
    _id: "$user"
  }},
  {$lookup:{
    from: "teste",
    let: { indice: "$_id" },
    pipeline: [
      {$group:{
        _id: null,
        user:{$sum:{$cond:[
          {$eq:[true, true]}, 1, 0
        ]}}
      }}
    ],
    as: "res"
  }}
])

//cond testada vamos extrair o que queremos
db.teste.aggregate([
  {$group:{
    _id: "$user"
  }},
  {$lookup:{
    from: "teste",
    let: { indice: "$_id" },
    pipeline: [
      {$group:{
        _id: null,
        user:{$sum:{$cond:[
          {$eq:["$user", "$$indice"]}, 1, 0
        ]}},
        last:{$sum:{$cond:[
          {$eq:["$last", "$$indice"]}, 1, 0
        ]}}
      }}
    ],
    as: "res"
  }}
])

//Vamos tirar o _id da sub-colection pois não precisamos dele
db.teste.aggregate([
  {$group:{
    _id: "$user"
  }},
  {$lookup:{
    from: "teste",
    let: { indice: "$_id" },
    pipeline: [
      {$group:{
        _id: null,
        user:{$sum:{$cond:[
          {$eq:["$user", "$$indice"]}, 1, 0
        ]}},
        last:{$sum:{$cond:[
          {$eq:["$last", "$$indice"]}, 1, 0
        ]}}
      }},
      {$project:{
        _id: 0
      }}
    ],
    as: "res"
  }}
])

Browser other questions tagged

You are not signed in. Login or sign up in order to post.