конвертировать значения в ключи в mongodb - PullRequest
0 голосов
/ 02 июля 2018

У меня есть документы MongoDB для размера рубашки, которые имеют эту форму:

{ "_id" : "L", "count" : 2.0 },
{ "_id" : "XL", "count" : 2.0 },
{ "_id" : "XXXL", "count" : 1.0 },
{ "_id" : "M", "count" : 1.0 }

Как вернуть один документ, соответствующий следующим критериям:

  • Возвращаемые значения, а не ключи
  • Заказ по размеру этикетки
  • Преобразование значений с плавающей запятой в целые числа
  • Вернуть метку размера рубашки со значением 0, если они не существуют

Желаемая форма:

{
  S: 0,
  M: 1,
  L: 2,
  XL: 2,
  XXL: 0,
  XXXL: 1
}

Ответы [ 3 ]

0 голосов
/ 02 июля 2018

без аггрейта:

RS-LAB:PRIMARY> db.shirtSize.find()
{ "_id" : "L", "count" : "2.0" }
{ "_id" : "XL", "count" : "2.0" }
{ "_id" : "XXXL", "count" : "1.0" }
{ "_id" : "M", "count" : "1.0" }
{ "_id" : "S", "count" : null }

RS-LAB:PRIMARY> 
db.shirtSize.find().sort({"count":1}).forEach(function(myShirts) { if 
(myShirts.count == null) {x = "0.0";} else {x = myShirts.count;} 
print(myShirts._id+"\t:\t"+parseInt(x));})

S   :   0
XXXL    :   1
M   :   1
L   :   2
XL  :   2
0 голосов
/ 03 июля 2018

Сначала нужно нажать все значения в массиве, используя $group каскад с парой k и v ... Затем извлечь пару ключ-значение с помощью arrayToObject агрегация и, наконец, вы должны проверить условие $ifNull для всех размеров

db.collection.aggregate([
  { "$group": {
    "_id": null,
    "array": {
      "$push": {
        "k": "$_id",
        "v": "$count"
      }
    }
  }},
  { "$replaceRoot": {
    "newRoot": { "$arrayToObject": "$array" }
  }},
  { "$addFields": {
    "S": { "$ifNull": ["$S", 0] },
    "M": { "$ifNull": ["$M", 0] },
    "L": { "$ifNull": ["$L", 0] },
    "XL": { "$ifNull": ["$XL",0]},
    "XXL": { "$ifNull": ["$XXL", 0]},
    "XXXL": { "$ifNull": ["$XXXL", 0] }
  }}
])

выход

[
  {
    "L": 2,
    "M": 1,
    "S": 0,
    "XL": 2,
    "XXL": 0,
    "XXXL": 1
  }
]

Проверьте это здесь

0 голосов
/ 02 июля 2018

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

db.col.aggregate([
    {
        $group: {
            _id: null,
            obj: { $push: { k: "$_id", v: "$count" } },
            keys: { $push: "$_id" }
        }
    },
    {
        $project: {
            obj: {
                $map: {
                    input: [ "S", "M", "L", "XL", "XXL", "XXXL" ],
                    as: "key",
                    in: {
                        $let: {  
                            vars: { keyIndex: { $indexOfArray: [ "$keys", "$$key" ] } },
                            in: {
                                $cond: {
                                    if: { $eq: [ "$$keyIndex", -1 ] },
                                    then: { k: "$$key", v: 0 },
                                    else: { $arrayElemAt: [ "$obj", "$$keyIndex" ] }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    {
        $replaceRoot: {
            newRoot: { $arrayToObject: "$obj" }
        }
    }
])

По сути, вы должны начать с накопления всех ключей и значений в одном объекте, используя $ group с _id, установленным на null. Затем для обеспечения порядка ключей, которые вам нужны, вы можете использовать $ map с постоянным массивом в качестве входных данных. Сопоставление должно проверить, существует ли каждый размер во входных данных (используя $ indexOfArray - возвращает -1 в противном случае) и принять это значение ( $ arrayElemAt ) или создать значение по умолчанию с 0 в противном случае. Логика ветвления может быть достигнута с помощью $ cond .

На последнем этапе конвейера вы можете использовать $ arrayToObject для преобразования этого массива k-v пар в один объект и $ replaceRoot для перевода этого объекта на корневой уровень.

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