MongoDB — распаковать строки из встроенного документа в отдельный столбец

Проблема

Итак, у меня есть документ MongoDB, который выглядит так:

Awards:


    [
      {
        "year": "2017",
        "winners": [
          {
            "name": "james",
            "id": 1
          },
          {
            "name": "adam",
            "id": 2
          }
        ]
      },
      {
        "year": "2018",
        "winners": [
          {
            "name": "mary",
            "id": 3
          },
          {
            "name": "jane",
            "id": 4
          }
        ]
      }
    ]

И я в основном пытаюсь расширить список победителей за каждый год, чтобы схема была примерно (year, winner_id), которую я могу позже использовать для присоединения, которое я планирую сделать. Что-то вроде этого:

[
   {
     "year":"2017",
     "winner_id":1
   },   
   {
     "year":"2017",
     "winner_id":2
   }, 
   {
     "year":"2018",
     "winner_id":3
   },
   {
     "year":"2018",
     "winner_id":4
   }
]

Что я пробовал

поэтому интуитивно я ищу что-то вроде $unwind, но проблема в том, что winners не является массивом.

  • Я пробовал db.awards.aggregate({'$unwind':'$winners.id'}), но это не сработало. (дал пустой результат)

  • Так что впоследствии я подумал db.awards.aggregate({'$unwind': {'$objectToArray':'$winners.id'}}), но это тоже не сработало. (выдал ошибку)

  • Согласно этот пост я должен сделать это:

db.awards.aggregate(
 { '$project': {
    _id: 1,
    'winners': 1
  } },
{'$unwind': '$winners'},
{'$unwind': '$winners.id'}
)

но даже это не сработало, я все равно получаю встроенный документ для каждого winner

Какие-нибудь мысли?


person QuantumHoneybees    schedule 15.11.2019    source источник
comment
Ваши отправленные документы недействительны json. Пожалуйста, сделайте репост их правильно   -  person Ashh    schedule 15.11.2019
comment
исправил их. извините, длинный день   -  person QuantumHoneybees    schedule 15.11.2019
comment
атрибут winners по-прежнему является объектом, а не массивом. Поэтому это все еще недействительный JSON. Вы действительно уверены, что winners не является массивом?   -  person thomas    schedule 15.11.2019
comment
да. это массив встроенных объектов. Это моя проблема :/   -  person QuantumHoneybees    schedule 15.11.2019


Ответы (2)


Ваши данные недействительны JSON. Предположим, что атрибут winners, скорее всего, является массивом.

Я вижу три дополнительные проблемы в ваших командах агрегации:

  1. Вы также должны передать конвейер агрегации в виде массива в функцию aggregate.
  2. синтаксис для $project отличается в конвейерах агрегации. Вы не определяете, какие поля должны быть включены. Вы определяете фактическое отображение
  3. Я не понимаю, почему вы хотите раскрутить id победителей. Атрибут для раскрутки должен быть массивом, а в вашем примере есть только массив winners.

Я думаю, что проще сделать $unwind перед проекцией

db.awards.aggregate(
  [
    {
      $unwind: { path: '$winners' }
    },
    {
      $project: {
        year: '$year',
        winner_id: '$winners.id'
      }
    }
  ]
);

Игровая площадка Mongo

person thomas    schedule 15.11.2019

Сначала вам необходимо $unwind winners и используйте $replaceRoot, чтобы получить это в корневом положении

db.collection.aggregate([
  { "$unwind": "$winners" },
  { "$replaceRoot": {
      "newRoot": {
        "$mergeObjects": [
          "$winners",
          { "year": "$year" }
        ]
      }
    }
  }
])

MongoPlayground

person Ashh    schedule 15.11.2019
comment
Мне нравится этот, replaceRoot очень мощный, и это, наконец, объяснило мне, что он делает! - person QuantumHoneybees; 15.11.2019