Mongodb 在动态键的情况下用于对象替换的聚合
Mongodb aggregation for object replacement in case of dynamic keys
假设我有以下集合 _id
和 traits
。
{
_id: 1,
traits: {
Rarity: {
infoin: 15,
},
Type: {
iron: 3,
sliver: 5,
wood: 7,
},
},
},
{
_id: 2,
traits: {
Cloth: {
barron1: 11,
barron2: 12,
},
Hair: {
black: 6,
yellow: 9,
red: 8
}
},
},
...
如您所见,traits
的键是动态的,子对象的键也是。
这是我想要得到的结果:
{
_id: 1,
traits: 15,
},
{
_id: 2,
traits: 23
}
Tip:
infocoin = iron + sliver + wood
barron1 + barron2 = black + yellow + red
$set
- 通过 $objectToArray
.
将对象转换为数组来设置 traitObjs
数组字段
$set
- 通过从 traitObjs
数组中获取第一个文档的值来设置 firstTraitValues
字段,然后通过 $objectToArray
从对象转换为数组.
$project
- 修饰输出文档。通过将 firstTraitValues
数组转换为具有 $reduce
和 $sum
所有 v
值的数字类型来设置 traits
字段。
db.collection.aggregate([
{
$set: {
traitObjs: {
$objectToArray: "$traits"
}
}
},
{
$set: {
firstTraitValues: {
$objectToArray: {
$first: "$traitObjs.v"
}
}
}
},
{
$project: {
traits: {
$reduce: {
input: "$firstTraitValues",
initialValue: 0,
in: {
$sum: [
"$$value",
"$$this.v"
]
}
}
}
}
}
])
由于traits
的第一个关键文件和第二个关键文件中的所有值都相同,
infocoin = iron + sliver + wood
barron1 + barron2 = black + yellow + red
因此上述方法只是总结了traits
的第一个关键文档中的所有值。
这个答案其实和@yong-shun'is 一样,只是把所有东西合二为一"$project"
。不知道会不会更高效
db.collection.aggregate([
{
"$project": {
"traits": {
"$reduce": {
"input": {
"$objectToArray": {
"$getField": {
"field": "v",
"input": { "$first": { "$objectToArray": "$traits" } }
}
}
},
"initialValue": 0,
"in": { "$sum": [ "$$value", "$$this.v" ] }
}
}
}
}
])
在 mongoplayground.net 上试用。
假设我有以下集合 _id
和 traits
。
{
_id: 1,
traits: {
Rarity: {
infoin: 15,
},
Type: {
iron: 3,
sliver: 5,
wood: 7,
},
},
},
{
_id: 2,
traits: {
Cloth: {
barron1: 11,
barron2: 12,
},
Hair: {
black: 6,
yellow: 9,
red: 8
}
},
},
...
如您所见,traits
的键是动态的,子对象的键也是。
这是我想要得到的结果:
{
_id: 1,
traits: 15,
},
{
_id: 2,
traits: 23
}
Tip:
infocoin = iron + sliver + wood
barron1 + barron2 = black + yellow + red
将对象转换为数组来设置$set
- 通过$objectToArray
.traitObjs
数组字段$set
- 通过从traitObjs
数组中获取第一个文档的值来设置firstTraitValues
字段,然后通过$objectToArray
从对象转换为数组.$project
- 修饰输出文档。通过将firstTraitValues
数组转换为具有$reduce
和$sum
所有v
值的数字类型来设置traits
字段。
db.collection.aggregate([
{
$set: {
traitObjs: {
$objectToArray: "$traits"
}
}
},
{
$set: {
firstTraitValues: {
$objectToArray: {
$first: "$traitObjs.v"
}
}
}
},
{
$project: {
traits: {
$reduce: {
input: "$firstTraitValues",
initialValue: 0,
in: {
$sum: [
"$$value",
"$$this.v"
]
}
}
}
}
}
])
由于traits
的第一个关键文件和第二个关键文件中的所有值都相同,
infocoin = iron + sliver + wood
barron1 + barron2 = black + yellow + red
因此上述方法只是总结了traits
的第一个关键文档中的所有值。
这个答案其实和@yong-shun'is "$project"
。不知道会不会更高效
db.collection.aggregate([
{
"$project": {
"traits": {
"$reduce": {
"input": {
"$objectToArray": {
"$getField": {
"field": "v",
"input": { "$first": { "$objectToArray": "$traits" } }
}
}
},
"initialValue": 0,
"in": { "$sum": [ "$$value", "$$this.v" ] }
}
}
}
}
])
在 mongoplayground.net 上试用。