как преобразовать поля mongodb в поля вложенных документов?

#mongodb

Вопрос:

извините, это может быть глупый вопрос, mongodb содержит тысячи документов .

трудно изменить вручную исходный формат

 {"name" : "aaaa",
 "price" : 111,
 "ing1" : "abcd",
"ing1Conc" : 50 ,
 "ing2" : "wxyz",
"ing2conc": 100}
 

необходимо было преобразовать в

 {"name" : "aaaa",
 "price" : 111,
 "content":[
    { "ing1" : "abcd", "ing1Conc" : 50},
    { "ing2" : "wxyz", "ing2conc": 100}
  ]
}
 

Комментарии:

1. Что вы пробовали до сих пор?

2.У вас всегда ing1 есть, ing1Conc , ing2 , ing2Conc или их больше ( ing3 ing3Conc т. е., ing4 , ing4Conc , и т.д.)

3. может быть 1 ингредиент или до 10 ингредиентов, каждый из которых содержит поля названия и концентрации

4. А как насчет смешанных случаев ing1Conc и ing2conc ? Это нарочно?

Ответ №1:

Тривиальным решением было бы вот это:

 db.collection.aggregate([
  {
    $project: {
      name: 1,
      price: 1,
      content: [
        { ing1: "$ing1", ing1Conc: "$ing1Conc" },
        { ing2: "$ing1", ing2conc: "$ing2conc" }
      ]
    }
  }
])
 

Более общим решением было бы следующее:

 db.collection.aggrega
  {
    $project: {
      name: 1,
      price: 1,
      data: {
        $filter: {
          input: { $objectToArray: "$ROOT" },
          cond: { $regexMatch: { input: "$this.k", regex: "^ing\d " } }
        }
      }
    }
  },
  { $unwind: "$data" },
  { $set: { i: { $regexFind: { input: "$data.k", regex: "\d " } } } },
  { $set: { i: "$i.match" } },
  {
    $group: {
      _id: {
        name: "$name",
        price: "$price",
        i: "$i"
      },
      content: { $push: "$data" }
    }
  },
  { $sort: { "_id.i": 1 } },      
  { $set: { content: { $arrayToObject: "$content" } } },
  {
    $group: {
      _id: { name: "$_id.name", price: "$_id.price" },
      content: { $push: "$content" }
    }
  },
  { $replaceRoot: { newRoot: { $mergeObjects: [ "$ROOT", "$_id" ] } } },
  { $unset: "_id" }
])
 

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

Однако я думаю, что эта структура все еще плоха. Я бы предложил что-то вроде

 content: { 
   ing: [ "abcd", "wxyz"], 
   conc: [ 50, 100 ]
}
content: [ 
  { ing: "abcd", conc: 50 }, 
  { ing: "wxyz", conc :100 }
]
content: [ 
  { idx: 1, ing: "abcd", conc: 50 }, 
  { idx: 2, ing: "wxyz", conc: 100 }
]