简体   繁体   中英

Last value by type with _id relation

I have a collection of Event containing a type that can be 0 , 1 , 2 , 3 , 4 , 5 and a createdAt date. Each event is related to an other collection called RTS.

I want to gather for each Rts, the last event of each type.

Problem using my soluce:

The problem is, I have to describe each types one by one in order to make it work. Is there any solution to have dynamical key creation induced by the type value?

Here is what I get now:

  1. I sort the data
  2. Group by idRTS whch contains the link to the second collection. For each type, push the values inside of a specific array.
  3. Remove the null values from the types arrays.
  4. Keep the first value only (the most updated) .
  5. Makes the data presentable.

[
  {
    $sort: {
      idRTS: -1,
      createdAt: -1
    }
  },
  {
    $group: {
      _id: '$idRTS',
      type0: {
        $push: {
          $cond: {
            if: {
              $eq: [
                '$type', 0
              ]
            },
            then: '$$ROOT',
            else: null
          }
        }
      },
      type5: {
        $push: {
          $cond: {
            if: {
              $eq: [
                '$type', 5
              ]
            },
            then: '$$ROOT',
            else: null
          }
        }
      }
    }
  },
  {
    $project: {
      _id: '$_id',
      type0: {
        '$filter': {
          'input': '$type0',
          'as': 'd',
          'cond': {
            '$ne': [
              '$$d', null
            ]
          }
        }
      },
      type5: {
        $filter: {
          input: '$type5',
          as: 'd',
          cond: {
            $ne: [
              '$$d', null
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      _id: '$_id',
      type0: {
        $arrayElemAt: [
          '$type0', 0
        ]
      },
      type5: {
        '$arrayElemAt': [
          '$type5', 0
        ]
      }
    }
  }
]
  • $match type in 0 or 5
  • $sort by idRTS and createdAt in descending order
  • $group by both idRTS and createdAt field and get first object, this will get first document of both type
  • $group by idRTS and make array of both types, in k(key) and v(value) format
  • $project to convert type array to object using $objectToArray
db.collection.aggregate([
  { $match: { type: { $in: [0, 5] } } },
  {
    $sort: {
      idRTS: -1,
      createdAt: -1
    }
  },
  {
    $group: {
      _id: {
        idRTS: "$idRTS",
        type: "$type"
      },
      type: { $first: "$$ROOT" }
    }
  },
  {
    $group: {
      _id: "$_id.idRTS",
      type: {
        $push: {
          k: { $toString: "$type.type" },
          v: "$type"
        }
      }
    }
  },
  { $project: { type: { $arrayToObject: "$type" } } }
])

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