将值转换为mongodb中的键

时间:2018-07-02 18:12:45

标签: mongodb aggregation-framework

我有有关衬衫尺寸的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 :(得分:2)

您需要先使用kv对使用$group阶段将数组中的所有值压入...然后使用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
  }
]

检查here

答案 1 :(得分:1)

您可以尝试以下汇总:

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来实现。

在最后一个管道阶段,您可以使用$arrayToObjectk-v对的数组转换为单个对象,并使用$replaceRoot将该对象提升到根级别。

答案 2 :(得分:0)

没有Aggragate:

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