根据键值计算聚合并使键成为 mongoDB 中的值
count aggregation base on key value and make keys become values in mongoDB
说明:我有几份文件,我想根据typ
统计,并想列出name
和date_key
。最后我们有 一个文档 ,即 typ
。请查看预期输出。
备注
typ
value is a variable.it 将只计算变量值的出现次数。
data
键包含一个元素,例如只有日期。但是我们需要键作为值,键可以是多个,目前有2个键,我可以有3个或更多。看到预期的输出键显示为列表 ["el1", "el2]
[
{
"typ": "ABC",
"data": [
{
"name": "XYZ",
"in_data": {
"date": {
"el2": "2015-01-10",
"el1": "2014-01-10"
},
"version" : "0.22",
"model" : "2015"
}
}
]
},
{
"typ": "ABC",
"data": [
{
"name": "LMNO",
"in_data": {
"date": {
"el2": "2015-01-10",
"el1": "2014-01-10"
},
"version" : "0.22",
"model" : "2014"
}
}
]
},
{
"typ": "EDC",
"data": [
{
"name": "QWERTY",
"in_data": {
"date": {
"el3": "2015-01-10",
"el4": "2014-01-10"
},
"version" : "0.52",
"model" : "2010"
}
}
]
}
]
预期输出
[
{
"typ_count" : 2,
"name" : ["XYZ", "LLMNO"],
"date_key" : ["el1", "el2"]
},
{
"typ_count" : 1,
"name" : ["QWERTY"],
"date_key" : ["el3", "el4"]
},
]
鉴于 data
字段是一个仅包含一个元素的数组,您只需使用 $unwind
, $first
or $arrayElemAt
运算符将其展平,但建议使用最后两个运算符中的任何一个以获得最佳效果聚合管道操作。
您的聚合管道基本上应该有 4 个阶段:初始阶段是将 data
键转换($addFields
管道)到嵌入式文档中,因为它作为数组的设计是多余的,因为它 只有有一个元素,最好把它压平,这样它就变成了嵌入文档。
下一个管道应该是另一个转换操作,您可以在其中使用 $map
and $objectToArray
创建 date
键的列表。
从那里你需要$group
the documents to aggregate the typ_count
using $sum
and create another list of the date
keys along with the name
list using $push
。
最终管道使用 $reduce
and $concatArrays
with a $cond
过滤掉上面生成的 date_key 列表中的重复项。
你的整体流水线应该如下
db.collection.aggregate([
{ $addFields: {
data: { $arrayElemAt: ['$data', 0] } // OR data: { $first: '$data' }
} },
{ $addFields: {
name: '$data.name',
date_key: {
$map: {
input: { $objectToArray: '$data.in_data.date' },
in: '$$this.k'
}
}
} },
{ $group: {
_id: '$typ',
typ_count: { $sum: 1 },
name: { $push: '$name' },
date_key: { $push: '$date_key' }
} },
{ $project: {
_id: 0,
typ_count: 1,
name: 1,
date_key: {
$reduce: {
input: '$date_key',
initialValue: [],
in: {
$concatArrays: [
'$$value',
{
$cond: [
{ $in: ["$$this", ["$$value"]] },
[],
"$$this"
]
}
]
}
}
}
} }
])
说明:我有几份文件,我想根据typ
统计,并想列出name
和date_key
。最后我们有 一个文档 ,即 typ
。请查看预期输出。
备注
typ
value is a variable.it 将只计算变量值的出现次数。data
键包含一个元素,例如只有日期。但是我们需要键作为值,键可以是多个,目前有2个键,我可以有3个或更多。看到预期的输出键显示为列表["el1", "el2]
[
{
"typ": "ABC",
"data": [
{
"name": "XYZ",
"in_data": {
"date": {
"el2": "2015-01-10",
"el1": "2014-01-10"
},
"version" : "0.22",
"model" : "2015"
}
}
]
},
{
"typ": "ABC",
"data": [
{
"name": "LMNO",
"in_data": {
"date": {
"el2": "2015-01-10",
"el1": "2014-01-10"
},
"version" : "0.22",
"model" : "2014"
}
}
]
},
{
"typ": "EDC",
"data": [
{
"name": "QWERTY",
"in_data": {
"date": {
"el3": "2015-01-10",
"el4": "2014-01-10"
},
"version" : "0.52",
"model" : "2010"
}
}
]
}
]
预期输出
[
{
"typ_count" : 2,
"name" : ["XYZ", "LLMNO"],
"date_key" : ["el1", "el2"]
},
{
"typ_count" : 1,
"name" : ["QWERTY"],
"date_key" : ["el3", "el4"]
},
]
鉴于 data
字段是一个仅包含一个元素的数组,您只需使用 $unwind
, $first
or $arrayElemAt
运算符将其展平,但建议使用最后两个运算符中的任何一个以获得最佳效果聚合管道操作。
您的聚合管道基本上应该有 4 个阶段:初始阶段是将 data
键转换($addFields
管道)到嵌入式文档中,因为它作为数组的设计是多余的,因为它 只有有一个元素,最好把它压平,这样它就变成了嵌入文档。
下一个管道应该是另一个转换操作,您可以在其中使用 $map
and $objectToArray
创建 date
键的列表。
从那里你需要$group
the documents to aggregate the typ_count
using $sum
and create another list of the date
keys along with the name
list using $push
。
最终管道使用 $reduce
and $concatArrays
with a $cond
过滤掉上面生成的 date_key 列表中的重复项。
你的整体流水线应该如下
db.collection.aggregate([
{ $addFields: {
data: { $arrayElemAt: ['$data', 0] } // OR data: { $first: '$data' }
} },
{ $addFields: {
name: '$data.name',
date_key: {
$map: {
input: { $objectToArray: '$data.in_data.date' },
in: '$$this.k'
}
}
} },
{ $group: {
_id: '$typ',
typ_count: { $sum: 1 },
name: { $push: '$name' },
date_key: { $push: '$date_key' }
} },
{ $project: {
_id: 0,
typ_count: 1,
name: 1,
date_key: {
$reduce: {
input: '$date_key',
initialValue: [],
in: {
$concatArrays: [
'$$value',
{
$cond: [
{ $in: ["$$this", ["$$value"]] },
[],
"$$this"
]
}
]
}
}
}
} }
])