Группировка агрегации MongoDB заполняет отсутствующие значения - PullRequest
1 голос
/ 06 августа 2020

Я использую структуру агрегации MongoDB. У меня есть коллекция Mon go с такими документами:

{
  'step': 1,
  'name': 'house',
  'score': 2
}
{
  'step': 1,
  'name': 'car',
  'score': 3
}
{
  'step': 2,
  'name': 'house',
  'score': 4
}

Я группирую документы с одним и тем же «шагом» и нажимаю «name» и «score» в массив объектов. Я получаю:

{
  'step': 1,
  'scores': 
  [
      {'name':'house','score':2},
      {'name':'car','score':3}
  ]
}
{
  'step': 2,
  'scores': 
  [
      {'name':'house','score':4}
  ]
}

Для каждого «шага» мне нужно скопировать значение предыдущего «шага» в случае, если «имя» не существует. У меня должно получиться что-то вроде этого:

{
      'step': 1,
      'scores': 
      [
          {'name':'house','score':2},
          {'name':'car','score':3}
      ]
    }
    {
      'step': 2,
      'scores': 
      [
          {'name':'house','score':4},
          **{'name': 'car', 'score':3}**
      ]
    }

Во втором документе элемент {'name': 'car', 'score': 3} был скопирован из предыдущего документа, потому что на этапе 'step: 2 «нет документов с« оценкой »для« автомобиль ».

Я не могу понять, как выполнить эту операцию с агрегацией MongoDB. Мы будем очень благодарны за некоторую помощь.

1 Ответ

0 голосов
/ 06 августа 2020

Требуется для использования $lookup с конвейером, смотрите пошагово ниже,

  • $group по step и pu sh все оценки в одном массиве scores
  • pu sh all name in names каждой оценки конкретного шага, мы будем использовать в условии соответствия внутри поиска
db.collection.aggregate([
  {
    $group: {
      _id: "$step",
      scores: {
        $push: {
          name: "$name",
          score: "$score"
        }
      },
      names: { $push: "$name" }
    }
  },
  • $unwind scores потому что его массив, и мы будем искать
  { $unwind: "$scores" },
  • $lookup let переменные step (_ id) и names для уровня конвейера
  • $match условие с выражением $expr есть 3 условия
    1. проверьте размер names Это должно быть одно (1), либо его car, либо house,
    2. номер шага совпадения, он должен быть равен
    3. совпадать not in, например. если car уже доступен, он будет искать house в поиске, необходимо использовать отдельные $not и $in
  • $project, чтобы отобразить обязательные поля
  • результат поиска будет сохранен в clone_score
  {
    $lookup: {
      from: "collection",
      let: {
        step_id: { $subtract: ["$_id", 1] },
        names: "$names"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                { $eq: [{ $size: "$$names" }, 1] },
                { $eq: ["$$step_id", "$step"] },
                { $not: [{ $in: ["$name", "$$names"] }] }
              ]
            }
          }
        },
        {
          $project: {
            _id: 0,
            name: 1,
            score: 1
          }
        }
      ],
      as: "clone_score"
    }
  },
  • $group по step (_ id) и pu sh все оценки в одном массиве scores, сначала сохранить clone_score
  {
    $group: {
      _id: "$_id",
      scores: { $push: "$scores" },
      clone_score: { $first: "$clone_score" }
    }
  },
  • из вышеуказанных конвейеров, теперь у нас есть два отдельных массива scores и clone_score,
  • $project нам нужно объединить их обоих в scores
  {
    $project: {
      _id: 0,
      step: "$_id",
      scores: {
        $concatArrays: ["$scores", "$clone_score"]
      }
    }
  }
])

Площадка: https://mongoplayground.net/p/Fytf7NEU7uG

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...