Сгруппируйте объекты с похожими данными и переформатируйте с помощью mongoose. - PullRequest
1 голос
/ 23 марта 2020

Javascript Группировать массив объектов с похожими данными и переформатировать с mon goose

mon goose получить элемент в массиве в агрегированном проекте

У меня есть массив объектов, которые Я хочу сгруппировать для получения этого результата

data:[{
        user_name: 'Jenny Lawrence',
        inner_data:[{
            "Back Pack":"Black",
            "produced":"2019",
            "manu_year":"2019",
            "item_state":"produced",
            "expiration":"unknown"
        },
        {
            other data belonging to jenny lawrence is formated like above
        }]
        "inner_data":{
            "detail":{"personal_item":"Baseball",
                    "manu_year":"2015","item_state":"purchased","color":"White","expiration":"unknown"}}
    }]

Это данные

"data":[
    {"user_name":"Jenny Lawrence", "inner_data":{
        "detail":{"personal_item":"Back Pack","manu_year":"2019","item_state":"produced",
                    "color":"Black","expiration":"unknown"}}},
    {"user_name":"Steven Benjjy",
        "inner_data":{
            "detail":{"personal_item":"Sneakers",
                    "manu_year":"2019","item_state":"purchased","color":"White","expiration":"unknown"}}},
    {"user_name":"Steven Benjjy",
        "inner_data":{
            "detail":{"personal_item":"Baseball",
                    "manu_year":"2018","item_state":"purchased","color":"White","expiration":"unknown"}}},
    {"user_name":"Jenny Lawrence",
        "inner_data":{
            "detail":{"personal_item":"Baseball",
                    "manu_year":"2015","item_state":"purchased","color":"White","expiration":"unknown"}}},
    {"user_name":"Jenny Lawrence",
        "inner_data":{
            "detail":{"personal_item":"iPhone",
                    "manu_year":"2019","item_state":"purchased","color":"White","expiration":"unknown"}}},
    {"user_name":"Daniel Stone",
        "inner_data":{
            "detail":{"personal_item":"Android Phone",
                    "manu_year":"2019","item_state":"purchased","color":"Stone grey","expiration":"unknown"}}},
    {"user_name":"Daniel Stone",
        "inner_data":{
            "detail":{"personal_item":"iPad",
                    "manu_year":"2019","item_state":"refurbished","color":"White","expiration":"unknown"}}}]}

Я хочу сгруппировать элементы по имени пользователя и сделать данные в personal_item как имя и значение цвета в качестве data / value и сделайте то же самое для item_state и manu_year, но поместите остальные в их обычном формате как объект массива.

Как я могу это сделать в пн goose

1 Ответ

0 голосов
/ 23 марта 2020

Вам необходимо использовать платформу агрегации MongoDB с определенными этапами / операторами:

db.collection.aggregate([
  /** group on user_name & push data to inner_data field */
  {
    $group: {
      _id: "$user_name",
      inner_data: {
        $push: {
          /** merge existing 'inner_data.detail' with new fields */
          $mergeObjects: [
            "$inner_data.detail",
            {
              /** As certain fields are being formed as an array, convert those to k:v pairs */
              $arrayToObject: [
                [
                  {
                    k: "$inner_data.detail.personal_item",
                    v: "$inner_data.detail.color"
                  },
                  {
                    k: "$inner_data.detail.item_state",
                    v: "$inner_data.detail.manu_year"
                  }
                ]
              ]
            }
          ]
        }
      }
    }
  },
  /** Optional, but this stage can be helpful to remove unnecessary fields */
  {
    $project: {
      "inner_data.color": 0,
      "inner_data.personal_item": 0
    }
  }
]);

Тест: MongoDB-Playground

Ref: $ mergeObjects , $ arrayToObject

Приведенный выше запрос дает одинаковую структуру inner_data для всех пользователей, если вы нужна такая преобразованная inner_data структура только для Дженни Лоуренс и для остальных других пользователей те же старые inner_data затем попробуйте это:

/** All the difference it brings is conditional check before push */
db.collection.aggregate([
  {
    $group: {
      _id: "$user_name",
      inner_data: {
        $push: {
          $cond: [
            {
              $eq: [
                "$user_name",
                "Jenny Lawrence"
              ]
            },
            {
              $mergeObjects: [
                "$inner_data.detail",
                {
                  $arrayToObject: [
                    [
                      {
                        k: "$inner_data.detail.personal_item",
                        v: "$inner_data.detail.color"
                      },
                      {
                        k: "$inner_data.detail.item_state",
                        v: "$inner_data.detail.manu_year"
                      }
                    ]
                  ]
                }
              ]
            },
            "$inner_data"
          ]
        }
      }
    }
  },
  {
    $project: {
      "inner_data.color": 0,
      "inner_data.personal_item": 0
    }
  }
])

Тест: MongoDB-Playground

...