Добавить поле с возрастающим значением в MongoDB Aggregation на основе условия - PullRequest
1 голос
/ 07 марта 2020

Образец моей коллекции:

[
  {
    _id: "bmasndvhjbcw",
    name: "lucas",
    occupation: "scientist",
    age: 55,
    location: "texas",
    joining_date: 2019-01-01T15:24:15.068+00:00
  },
  {
    _id: "bmasndvhjbcx",
    name: "mark",
    occupation: "scientist",
    age: 45,
    location: "texas",
    joining_date: 2019-01-01T15:24:15.068+00:00
  },
  {
    _id: "bmasndvhjbca",
    name: "stuart",
    occupation: "lab assistant",
    age: 25,
    location: "texas",
    joining_date: 2019-01-02T20:25:16.068+00:00
  },
  {
    _id: "bmasndvhjbcq",
    name: "cooper",
    occupation: "physicist",
    age: 69,
    location: "texas"
  }
]

В каких документах есть столбец joining_date , необходимо добавить поле с возрастающим значением, проверив дату как joining_date_count:1

если даты совпадают, как в двух случаях mark и lucas. count должен рассматривать его как разные значения и увеличивать счет.

Ожидаемый результат:

[
  {
    _id: "bmasndvhjbcw",
    name: "lucas",
    occupation: "scientist",
    age: 55,
    location: "texas",
    joining_date: 2019-01-01T15:24:15.068+00:00,
    joining_date_count:1
  },
  {
    _id: "bmasndvhjbcx",
    name: "mark",
    occupation: "scientist",
    age: 45,
    location: "texas",
    joining_date: 2019-01-01T15:24:15.068+00:00,
    joining_date_count:2
  },
  {
    _id: "bmasndvhjbca",
    name: "stuart",
    occupation: "lab assistant",
    age: 25,
    location: "texas",
    joining_date: 2019-01-02T20:25:16.068+00:00,
    joining_date_count:3
  },
  {
    _id: "bmasndvhjbcq",
    name: "cooper",
    occupation: "physicist",
    age: 69,
    location: "texas"
  }
]

Ответы [ 2 ]

2 голосов
/ 07 марта 2020

Эта агрегация добавляет поле со счетчиком:

db.collection.aggregate( [
  { 
      $match: { 
          joining_date: { $exists: true } 
      } 
  },
  { 
      $group: { 
          _id: null, 
          docs: { $push: "$$ROOT" } 
      } 
  },
  { 
      $project: { 
          _id: 0,
         R: { 
             $map: {
                 input: { $range: [ 0, { $size: "$docs" } ] },
                 in: {
                     $mergeObjects: [ 
                         { joining_date_count: { $add: [ "$$this", 1 ] } },
                         { $arrayElemAt: [ "$docs", "$$this" ] }
                     ]
                 }
             }
         }
      }
  },
  { 
      $unwind: "$R" 
  },
  { 
      $replaceRoot: { newRoot: "$R" } 
  }
] )
1 голос
/ 07 марта 2020

Вы можете попробовать запрос ниже:

db.collection.aggregate([
    /** Sort on joining_date field which will arrange docs with missing field at top & ascending where field exists */
    {
      $sort: {
        joining_date: 1
      }
    },
    /** group on empty & push every doc in collection to an array field named data */
    {
      $group: {
        _id: "",
        data: {
          $push: "$$ROOT"
        }
      }
    },
    /** split data array into two array one has doc which doesn't field & other has docs which does have field */
    {
      $addFields: {
        data: {
          $reduce: {
            input: "$data",
            initialValue: {
              missingField: [],
              fieldExists: []
            },
            in: {
              missingField: {
                $cond: [
                  {
                    "$ifNull": [
                      "$$this.joining_date",
                      false
                    ]
                  },
                  "$$value.missingField",
                  {
                    $concatArrays: [
                      "$$value.missingField",
                      [
                        "$$this"
                      ]
                    ]
                  }
                ]
              },
              fieldExists: {
                $cond: [
                  {
                    "$ifNull": [
                      "$$this.joining_date",
                      false
                    ]
                  },
                  {
                    $concatArrays: [
                      "$$value.fieldExists",
                      [
                        "$$this"
                      ]
                    ]
                  },
                  "$$value.fieldExists"
                ]
              }
            }
          }
        }
      }
    },
    /** Add new field 'joining_date_count' to docs based on that doc index in fieldExists array &
     *  finally concatinate missingField with newly formed fieldExists array */
    {
      $addFields: {
        "data": {
          $concatArrays: [
            "$data.missingField",
            {
              $map: {
                input: "$data.fieldExists",
                in: {
                  $mergeObjects: [
                    "$$this",
                    {
                      joining_date_count: {
                        $add: [
                          1,
                          {
                            $indexOfArray: [
                              "$data.fieldExists",
                              "$$this"
                            ]
                          }
                        ]
                      }
                    }
                  ]
                }
              }
            }
          ]
        }
      }
    },
    /** unwind data array */
    {
      $unwind: "$data"
    },
    /** replace each docs root as data field */
    {
      $replaceRoot: {
        newRoot: "$data"
      }
    }
  ])

Тест: MongoDB-Playground

...