MongoDB aggregate,如何在group pipeline中addToSet数组的每个元素
MongoDB aggregate, how to addToSet each element of array in group pipeline
我有包含标签字段的文档。这是一个简单的数组,里面有标签名称,里面没有对象,也没有 _id。
只是像这样的普通标签 ["Protocol", "Access", "Leverage", "Capability"]
.
在我的小组管道中,我尝试了类似 'selectedTags': { $addToSet: '$tags' }
的方法,但最终我得到了一个包含标签数组的数组。我对 $push
.
也一样
我尝试使用 $each
或 $pushAll
,但正如 shell 告诉我的那样,它们不支持作为分组运算符。
有人可以帮我解决这个问题吗?
谢谢
编辑:
示例文档:
{
"_id" : "HWEdDGsq86x4ikDSQ",
"teamId" : "AdLizGnPuqbWNsFHe",
"ownerId" : "Qb5EigWjqn2t3bfxD",
"type" : "meeting",
"topic" : "Grass-roots hybrid knowledge user",
"fullname" : "Guidouil",
"startDate" : ISODate("2017-07-30T09:00:05.513Z"),
"shareResults" : true,
"open" : true,
"language" : "fr",
"tags" : [
"Protocol",
"Challenge",
"Artificial Intelligence",
"Capability"
],
"isDemo" : true,
"createdAt" : ISODate("2017-11-15T19:24:05.513Z"),
"participantsCount" : 10,
"ratersCount" : 10,
"averageRating" : 3.4,
"hasAnswers" : true,
"updatedAt" : ISODate("2017-11-15T19:24:05.562Z")
}
{
"_id" : "rXvkFndpXwJ6KAvNo",
"teamId" : "AdLizGnPuqbWNsFHe",
"ownerId" : "Qb5EigWjqn2t3bfxD",
"type" : "meeting",
"topic" : "Profit-focused modular system engine",
"fullname" : "Guidouil",
"startDate" : ISODate("2017-07-24T12:00:05.564Z"),
"shareResults" : true,
"open" : true,
"language" : "fr",
"tags" : [
"Initiative",
"Artificial Intelligence",
"Protocol",
"Utilisation"
],
"isDemo" : true,
"createdAt" : ISODate("2017-11-15T19:24:05.564Z"),
"participantsCount" : 33,
"ratersCount" : 33,
"averageRating" : 2.9393939393939394,
"hasAnswers" : true,
"updatedAt" : ISODate("2017-11-15T19:24:05.753Z")
}
聚合:
db.surveys.aggregate(
{ $match: query },
{
$group: {
'_id': {
'year': { $year: '$startDate' },
'day': { $dayOfYear: '$startDate' },
},
'participants': { $sum: '$ratersCount' },
'rating': { $avg: '$averageRating' },
'surveys': { $push: '$_id' },
'selectedTags': { $addToSet: '$tags' },
'peoples': { $addToSet: '$fullname' },
}
},
{ $sort: { _id: 1 } }
);
然后我尝试将 selectedTags 更改为 { $push: { $each: '$tags' } }
或 { $pushAll: '$tags' }
但这不会执行 :(
编辑 2:
在javascript我是这样做的:
return Surveys.aggregate(
{ $match: query },
{ $group: {
_id: dateGroup,
participants: { $sum: '$ratersCount' },
rating: { $avg: '$averageRating' },
surveys: { $push: '$_id' },
selectedTags: { $push: '$tags' },
peoples: { $addToSet: '$fullname' },
} },
{ $project: {
_id: null,
selectedTags: {
$reduce: {
input: "$selectedTags",
initialValue: [],
in: { $setUnion: ["$$value", "$$this"] }
}
},
} }
);
在投影舞台上模仿 $addToSet update operator with $each modifier in aggregation pipeline you can use a combination of $push on grouping stage and $reduce + $setUnion 的功能。例如:
db.collection.aggregate([
{$group:{
_id: null,
selectedTags: { $push: '$tags' }
}},
{$project: {
selectedTags: { $reduce: {
input: "$selectedTags",
initialValue: [],
in: {$setUnion : ["$$value", "$$this"]}
}}
}}
])
单个文档的结果包含 selectedTags
数组中所有文档的不同标签列表。
您也可以使用$unwind得到结果:
db.collection.aggregate([
{$unwind: "$tags"},
{$group:{
_id: null,
selectedTags: { $addToSet: '$tags' }
}}
])
Dannyxu 和 Alex Beck 的回答都有效,但在小组赛阶段使用时仅部分有效。我需要将两者结合起来以获得单个平面标签数组的预期结果:
Model.aggregate()
.match({ /** some query */ })
.group({
_id: '$teamId',
tagsSet: { $push: '$tags' },
numRecords: { $sum: 1 },
})
.project({
_id: 0,
numRecords: 1,
tagsSet: {
$reduce: {
input: '$tagsSet',
initialValue: [],
in: { $setUnion: ['$$value', '$$this'] },
},
},
})
.unwind({ path: '$tagsSet' })
.group({
_id: null,
selectedTags: { $addToSet: '$tagsSet' },
numRecords: { $sum: '$numRecords' },
})
我有包含标签字段的文档。这是一个简单的数组,里面有标签名称,里面没有对象,也没有 _id。
只是像这样的普通标签 ["Protocol", "Access", "Leverage", "Capability"]
.
在我的小组管道中,我尝试了类似 'selectedTags': { $addToSet: '$tags' }
的方法,但最终我得到了一个包含标签数组的数组。我对 $push
.
我尝试使用 $each
或 $pushAll
,但正如 shell 告诉我的那样,它们不支持作为分组运算符。
有人可以帮我解决这个问题吗?
谢谢
编辑:
示例文档:
{
"_id" : "HWEdDGsq86x4ikDSQ",
"teamId" : "AdLizGnPuqbWNsFHe",
"ownerId" : "Qb5EigWjqn2t3bfxD",
"type" : "meeting",
"topic" : "Grass-roots hybrid knowledge user",
"fullname" : "Guidouil",
"startDate" : ISODate("2017-07-30T09:00:05.513Z"),
"shareResults" : true,
"open" : true,
"language" : "fr",
"tags" : [
"Protocol",
"Challenge",
"Artificial Intelligence",
"Capability"
],
"isDemo" : true,
"createdAt" : ISODate("2017-11-15T19:24:05.513Z"),
"participantsCount" : 10,
"ratersCount" : 10,
"averageRating" : 3.4,
"hasAnswers" : true,
"updatedAt" : ISODate("2017-11-15T19:24:05.562Z")
}
{
"_id" : "rXvkFndpXwJ6KAvNo",
"teamId" : "AdLizGnPuqbWNsFHe",
"ownerId" : "Qb5EigWjqn2t3bfxD",
"type" : "meeting",
"topic" : "Profit-focused modular system engine",
"fullname" : "Guidouil",
"startDate" : ISODate("2017-07-24T12:00:05.564Z"),
"shareResults" : true,
"open" : true,
"language" : "fr",
"tags" : [
"Initiative",
"Artificial Intelligence",
"Protocol",
"Utilisation"
],
"isDemo" : true,
"createdAt" : ISODate("2017-11-15T19:24:05.564Z"),
"participantsCount" : 33,
"ratersCount" : 33,
"averageRating" : 2.9393939393939394,
"hasAnswers" : true,
"updatedAt" : ISODate("2017-11-15T19:24:05.753Z")
}
聚合:
db.surveys.aggregate(
{ $match: query },
{
$group: {
'_id': {
'year': { $year: '$startDate' },
'day': { $dayOfYear: '$startDate' },
},
'participants': { $sum: '$ratersCount' },
'rating': { $avg: '$averageRating' },
'surveys': { $push: '$_id' },
'selectedTags': { $addToSet: '$tags' },
'peoples': { $addToSet: '$fullname' },
}
},
{ $sort: { _id: 1 } }
);
然后我尝试将 selectedTags 更改为 { $push: { $each: '$tags' } }
或 { $pushAll: '$tags' }
但这不会执行 :(
编辑 2:
在javascript我是这样做的:
return Surveys.aggregate(
{ $match: query },
{ $group: {
_id: dateGroup,
participants: { $sum: '$ratersCount' },
rating: { $avg: '$averageRating' },
surveys: { $push: '$_id' },
selectedTags: { $push: '$tags' },
peoples: { $addToSet: '$fullname' },
} },
{ $project: {
_id: null,
selectedTags: {
$reduce: {
input: "$selectedTags",
initialValue: [],
in: { $setUnion: ["$$value", "$$this"] }
}
},
} }
);
在投影舞台上模仿 $addToSet update operator with $each modifier in aggregation pipeline you can use a combination of $push on grouping stage and $reduce + $setUnion 的功能。例如:
db.collection.aggregate([
{$group:{
_id: null,
selectedTags: { $push: '$tags' }
}},
{$project: {
selectedTags: { $reduce: {
input: "$selectedTags",
initialValue: [],
in: {$setUnion : ["$$value", "$$this"]}
}}
}}
])
单个文档的结果包含 selectedTags
数组中所有文档的不同标签列表。
您也可以使用$unwind得到结果:
db.collection.aggregate([
{$unwind: "$tags"},
{$group:{
_id: null,
selectedTags: { $addToSet: '$tags' }
}}
])
Dannyxu 和 Alex Beck 的回答都有效,但在小组赛阶段使用时仅部分有效。我需要将两者结合起来以获得单个平面标签数组的预期结果:
Model.aggregate()
.match({ /** some query */ })
.group({
_id: '$teamId',
tagsSet: { $push: '$tags' },
numRecords: { $sum: 1 },
})
.project({
_id: 0,
numRecords: 1,
tagsSet: {
$reduce: {
input: '$tagsSet',
initialValue: [],
in: { $setUnion: ['$$value', '$$this'] },
},
},
})
.unwind({ path: '$tagsSet' })
.group({
_id: null,
selectedTags: { $addToSet: '$tagsSet' },
numRecords: { $sum: '$numRecords' },
})