我有有关衬衫尺寸的MongoDB文档,其形状如下:
{ "_id" : "L", "count" : 2.0 },
{ "_id" : "XL", "count" : 2.0 },
{ "_id" : "XXXL", "count" : 1.0 },
{ "_id" : "M", "count" : 1.0 }
如何返回符合以下条件的单个文档:
所需形状:
{
S: 0,
M: 1,
L: 2,
XL: 2,
XXL: 0,
XXXL: 1
}
答案 0 :(得分:2)
您需要先使用k
和v
对使用$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来实现。
在最后一个管道阶段,您可以使用$arrayToObject将k-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