将分组的结果合并到 Mongo 中的一个文档中
merge grouped results into one document in Mongo
我有一个这样的文档
{
"_id": {
"$oid": "6187e5fa4ebcc2db6c86081f"
},
"publicId": "S23DCL",
"flights": [
{
"name": "f1",
"_id": {
"$oid": "620026293fc350024da614dd"
},
"wines": [
{
"id": "1",
"name": "wine1"
},
{
"id": "2",
"name": "wine2"
}
]
},
{
"name": "f2",
"_id": {
"$oid": "6200263c3fc350024da614de"
},
"wines": [
{
"id": "3",
"name": "leVin"
},
{
"id": "4",
"name": "theWine"
}
]
}
],
"title": "Pinot Noir 2022",
"scores": [
{
"userId": "f8Dv",
"userName": "gugus",
"scores": [
{
"score": 95,
"wineId": "1"
},
{
"score": 88,
"wineId": "2"
}
]
},
{
"userId": "yLjh",
"userName": "test",
"scores": [
{
"score": 92,
"wineId": "1"
},
{
"score": 87,
"wineId": "2"
}
]
},
{
"userId": "B6em",
"userName": "jklsdf",
"scores": [
{
"score": 88,
"wineId": "1"
},
{
"score": 90,
"wineId": "2"
},
{
"score": 92,
"wineId": "3"
},
{
"score": 86,
"wineId": "4"
}
],
"isFinished": false
}
],
}
如果问题太长我可以缩短它。
整个文档和查询也可以是found in mongoplayground
我想做的是为所有葡萄酒创建一个记分牌,这意味着为每种葡萄酒计算平均等,同时仍然只有一个文档。
像这样
{
"title": "Pinot Noir 2022"
"results": [
{
"wine": {
"flightName": "f1",
"wineIndex": 1,
"name": "wine1",
"wineId": "1"
},
"avg": 90,
"scores": [
{
"scores": {
"score": 87,
"wineId": "1"
},
"userId": "yLjh",
"userName": "test"
},
]
}
]
}
我快完成了,但是我在分组后想要一个结果文档的部分遇到了困难。
scores中的wineId对应flights.wines
中的id
这是我目前所拥有的
db.collection.aggregate([
{
"$match": {
"publicId": "S23DCL"
}
},
{
"$project": {
"scores": "$scores",
"publicId": "$publicId"
}
},
{
"$unwind": "$scores"
},
{
"$unwind": "$scores.scores"
},
{
$lookup: {
from: "collection",
let: {
wId: "$scores.scores.wineId",
"tastingId": "$_id"
},
pipeline: [
{
"$unwind": "$flights"
},
{
"$unwind": {
"path": "$flights.wines",
"includeArrayIndex": "index"
}
},
{
$match: {
$expr: {
"$and": [
{
"$eq": [
"$flights.wines.id",
"$$wId"
]
},
{
"$eq": [
"$_id",
"$$tastingId"
]
}
]
},
}
},
{
$project: {
_id: 0,
"name": "$flights.wines.name",
"flight": "$flights.name",
"wineId": "$flights.wines.id",
"index": "$index"
}
}
],
as: "wine"
}
},
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{
"_id": "$_id",
"scores": "$scores"
},
{
"wine": {
"$arrayElemAt": [
"$wine",
0
]
}
}
]
}
}
},
{
"$group": {
"_id": "$wine",
"avg": {
"$avg": "$scores.scores.score"
},
"min": {
"$min": "$scores.scores.score"
},
"max": {
"$max": "$scores.scores.score"
},
"stddev": {
"$stdDevPop": "$scores.scores.score"
},
"tmp": {
"$max": 1
},
"scores": {
"$addToSet": "$scores"
}
}
}
])
这给了我上面 results
中看到的数据。但是缺少像“标题”这样的数据。
请注意 tmp
字段。我试图在后期添加这个虚拟字段并对其进行分组。
因为总是只有一组(因为 tmp 是静态的)。
喜欢
// query from abive
,{
"$group": {
"$_id": "tmp"
// add my grouped results from before into an array
}
}
那么如何将分组结果添加到一个数组中,这样我就不会返回 (n) 个组,而是得到分组结果在数组中的一个文档?
希望你明白我的意思:)
也许是这样的:
{
$group: {
_id: "tmp",
array: {
$push: "$$ROOT"
}
}
}
当您使用 replaceRoot 替换根目录时,您的标题丢失了。首先,您必须将它添加到新的根级别。
这个 returns 你的标题 .
[
{
'$match': {
'publicId': 'S23DCL'
}
}, {
'$project': {
'scores': '$scores',
'publicId': '$publicId',
'title': '$title',
'flights': '$flights'
}
}, {
'$unwind': '$scores'
}, {
'$unwind': '$scores.scores'
}, {
'$lookup': {
'from': 'collection',
'let': {
'wId': '$scores.scores.wineId',
'tastingId': '$_id'
},
'pipeline': [
{
'$unwind': '$flights'
}, {
'$unwind': {
'path': '$flights.wines',
'includeArrayIndex': 'index'
}
}, {
'$match': {
'$expr': {
'$and': [
{
'$eq': [
'$flights.wines.id', '$$wId'
]
}, {
'$eq': [
'$_id', '$$tastingId'
]
}
]
}
}
}, {
'$project': {
'_id': 0,
'name': '$flights.wines.name',
'flight': '$flights.name',
'wineId': '$flights.wines.id',
'index': '$index'
}
}
],
'as': 'wine'
}
}, {
'$addFields': {
'scores.title': '$title'
}
}, {
'$replaceRoot': {
'newRoot': {
'$mergeObjects': [
{
'_id': '$_id',
'scores': '$scores'
}, {
'wine': {
'$arrayElemAt': [
'$wine', 0
]
}
}
]
}
}
}, {
'$group': {
'_id': '$wine',
'title': {
'$last': '$scores.title'
},
'avg': {
'$avg': '$scores.scores.score'
},
'min': {
'$min': '$scores.scores.score'
},
'max': {
'$max': '$scores.scores.score'
},
'stddev': {
'$stdDevPop': '$scores.scores.score'
},
'tmp': {
'$max': 1
},
'scores': {
'$addToSet': '$scores'
}
}
}
]
但是您当前的聚合管道有太多阶段。如果您解释一下您的数据源究竟需要什么,它可能需要稍微优化一下
我有一个这样的文档
{
"_id": {
"$oid": "6187e5fa4ebcc2db6c86081f"
},
"publicId": "S23DCL",
"flights": [
{
"name": "f1",
"_id": {
"$oid": "620026293fc350024da614dd"
},
"wines": [
{
"id": "1",
"name": "wine1"
},
{
"id": "2",
"name": "wine2"
}
]
},
{
"name": "f2",
"_id": {
"$oid": "6200263c3fc350024da614de"
},
"wines": [
{
"id": "3",
"name": "leVin"
},
{
"id": "4",
"name": "theWine"
}
]
}
],
"title": "Pinot Noir 2022",
"scores": [
{
"userId": "f8Dv",
"userName": "gugus",
"scores": [
{
"score": 95,
"wineId": "1"
},
{
"score": 88,
"wineId": "2"
}
]
},
{
"userId": "yLjh",
"userName": "test",
"scores": [
{
"score": 92,
"wineId": "1"
},
{
"score": 87,
"wineId": "2"
}
]
},
{
"userId": "B6em",
"userName": "jklsdf",
"scores": [
{
"score": 88,
"wineId": "1"
},
{
"score": 90,
"wineId": "2"
},
{
"score": 92,
"wineId": "3"
},
{
"score": 86,
"wineId": "4"
}
],
"isFinished": false
}
],
}
如果问题太长我可以缩短它。
整个文档和查询也可以是found in mongoplayground
我想做的是为所有葡萄酒创建一个记分牌,这意味着为每种葡萄酒计算平均等,同时仍然只有一个文档。
像这样
{
"title": "Pinot Noir 2022"
"results": [
{
"wine": {
"flightName": "f1",
"wineIndex": 1,
"name": "wine1",
"wineId": "1"
},
"avg": 90,
"scores": [
{
"scores": {
"score": 87,
"wineId": "1"
},
"userId": "yLjh",
"userName": "test"
},
]
}
]
}
我快完成了,但是我在分组后想要一个结果文档的部分遇到了困难。
scores中的wineId对应flights.wines
这是我目前所拥有的
db.collection.aggregate([
{
"$match": {
"publicId": "S23DCL"
}
},
{
"$project": {
"scores": "$scores",
"publicId": "$publicId"
}
},
{
"$unwind": "$scores"
},
{
"$unwind": "$scores.scores"
},
{
$lookup: {
from: "collection",
let: {
wId: "$scores.scores.wineId",
"tastingId": "$_id"
},
pipeline: [
{
"$unwind": "$flights"
},
{
"$unwind": {
"path": "$flights.wines",
"includeArrayIndex": "index"
}
},
{
$match: {
$expr: {
"$and": [
{
"$eq": [
"$flights.wines.id",
"$$wId"
]
},
{
"$eq": [
"$_id",
"$$tastingId"
]
}
]
},
}
},
{
$project: {
_id: 0,
"name": "$flights.wines.name",
"flight": "$flights.name",
"wineId": "$flights.wines.id",
"index": "$index"
}
}
],
as: "wine"
}
},
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{
"_id": "$_id",
"scores": "$scores"
},
{
"wine": {
"$arrayElemAt": [
"$wine",
0
]
}
}
]
}
}
},
{
"$group": {
"_id": "$wine",
"avg": {
"$avg": "$scores.scores.score"
},
"min": {
"$min": "$scores.scores.score"
},
"max": {
"$max": "$scores.scores.score"
},
"stddev": {
"$stdDevPop": "$scores.scores.score"
},
"tmp": {
"$max": 1
},
"scores": {
"$addToSet": "$scores"
}
}
}
])
这给了我上面 results
中看到的数据。但是缺少像“标题”这样的数据。
请注意 tmp
字段。我试图在后期添加这个虚拟字段并对其进行分组。
因为总是只有一组(因为 tmp 是静态的)。
喜欢
// query from abive
,{
"$group": {
"$_id": "tmp"
// add my grouped results from before into an array
}
}
那么如何将分组结果添加到一个数组中,这样我就不会返回 (n) 个组,而是得到分组结果在数组中的一个文档?
希望你明白我的意思:)
也许是这样的:
{
$group: {
_id: "tmp",
array: {
$push: "$$ROOT"
}
}
}
当您使用 replaceRoot 替换根目录时,您的标题丢失了。首先,您必须将它添加到新的根级别。 这个 returns 你的标题 .
[
{
'$match': {
'publicId': 'S23DCL'
}
}, {
'$project': {
'scores': '$scores',
'publicId': '$publicId',
'title': '$title',
'flights': '$flights'
}
}, {
'$unwind': '$scores'
}, {
'$unwind': '$scores.scores'
}, {
'$lookup': {
'from': 'collection',
'let': {
'wId': '$scores.scores.wineId',
'tastingId': '$_id'
},
'pipeline': [
{
'$unwind': '$flights'
}, {
'$unwind': {
'path': '$flights.wines',
'includeArrayIndex': 'index'
}
}, {
'$match': {
'$expr': {
'$and': [
{
'$eq': [
'$flights.wines.id', '$$wId'
]
}, {
'$eq': [
'$_id', '$$tastingId'
]
}
]
}
}
}, {
'$project': {
'_id': 0,
'name': '$flights.wines.name',
'flight': '$flights.name',
'wineId': '$flights.wines.id',
'index': '$index'
}
}
],
'as': 'wine'
}
}, {
'$addFields': {
'scores.title': '$title'
}
}, {
'$replaceRoot': {
'newRoot': {
'$mergeObjects': [
{
'_id': '$_id',
'scores': '$scores'
}, {
'wine': {
'$arrayElemAt': [
'$wine', 0
]
}
}
]
}
}
}, {
'$group': {
'_id': '$wine',
'title': {
'$last': '$scores.title'
},
'avg': {
'$avg': '$scores.scores.score'
},
'min': {
'$min': '$scores.scores.score'
},
'max': {
'$max': '$scores.scores.score'
},
'stddev': {
'$stdDevPop': '$scores.scores.score'
},
'tmp': {
'$max': 1
},
'scores': {
'$addToSet': '$scores'
}
}
}
]
但是您当前的聚合管道有太多阶段。如果您解释一下您的数据源究竟需要什么,它可能需要稍微优化一下