我正在进行版本控制,我们有基于UUIDs
和jobUuids
的文档,而jobUuids
是与当前工作的用户关联的文档。我对这些集合有一些汇总查询,我需要根据作业UUID更新这些查询,
通过聚合查询获取的结果应为
jobUuid
文档不存在,则将返回带有jobUuid: "default"
的主文档(该文档不包含任何jobUuid)我有一个$match
用于根据特定条件获取这些文档,我需要根据上述条件从这些文档中过滤掉文档,并在下面显示一个示例,
数据如下:
[
{
"uuid": "5cdb5a10-4f9b-4886-98c1-31d9889dd943",
"name": "adam",
"jobUuid": "default",
},
{
"uuid": "5cdb5a10-4f9b-4886-98c1-31d9889dd943",
"jobUuid": "d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12",
"name": "adam"
},
{
"uuid": "b745baff-312b-4d53-9438-ae28358539dc",
"name": "eve",
"jobUuid": "default",
},
{
"uuid": "b745baff-312b-4d53-9438-ae28358539dc",
"jobUuid": "d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12",
"name": "eve"
},
{
"uuid": "26cba689-7eb6-4a9e-a04e-24ede0309e50",
"name": "john",
"jobUuid": "default",
}
]
"jobUuid": "d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12"
的结果应为:
[
{
"uuid": "5cdb5a10-4f9b-4886-98c1-31d9889dd943",
"jobUuid": "d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12",
"name": "adam"
},
{
"uuid": "b745baff-312b-4d53-9438-ae28358539dc",
"jobUuid": "d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12",
"name": "eve"
},
{
"uuid": "26cba689-7eb6-4a9e-a04e-24ede0309e50",
"name": "john",
"jobUuid": "default",
}
]
基于上述条件,是否可以在聚合查询中过滤文档以提取特定作业uuid的文档?
编辑1:我得到了以下解决方案,效果很好,我想要一个更好的解决方案,消除所有这些嵌套阶段。
编辑2:使用实际的UUID更新了数据,我仅将name
作为另一个字段,我们确实有n
个字段,这些字段与此处无关,但最后需要(针对那些想在所有字段上使用投影的人都提及了这一点。)
答案 0 :(得分:3)
根据评论进行更新:
,但是UUID是字母数字字符串,如上所示,它是否具有 对这些排序的影响,并且由于我们没有使用条件 得到结果,我担心这会引起问题。
您可以使用其他字段来匹配排序顺序,使其与in表达式中的值相同。确保您提供默认值作为最后一个值。
[
{"$match":{"jobUuid":{"$in":["d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12","default"]}}},
{"$addFields":{ "order":{"$indexOfArray":[["d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12","default"], "$jobUuid"]}}},
{"$sort":{"uuid":1, "order":1}},
{
"$group": {
"_id": "$uuid",
"doc":{"$first":"$$ROOT"}
}
},
{"$project":{"doc.order":0}},
{"$replaceRoot":{"newRoot":"$doc"}}
]
此处的示例-https://mongoplayground.net/p/wXiE9i18qxf
原始
您可以使用以下查询。如果存在用于uuid的查询,则查询将选择非默认文档,否则将选择默认文档作为唯一文档。
[
{"$match":{"jobUuid":{"$in":[1,"default"]}}},
{"$sort":{"uuid":1, "jobUuid":1}},
{
"$group": {
"_id": "$uuid",
"doc":{"$first":"$$ROOT"}
}
},
{"$replaceRoot":{"newRoot":"$doc"}}
]
答案 1 :(得分:1)
这就是我要做的:
经过以下测试:https://mongoplayground.net/p/e76cVJf0F3o
[{
"$match": {
"jobUuid": {
"$in": [
"1",
"default"
]
}
}
},
{
"$group": {
"_id": "$uuid",
"name": {
"$first": "$name"
},
"jobUuids": {
"$addToSet": {
"$cond": {
"if": {
"$ne": [
"$jobUuid",
"default"
]
},
"then": "$jobUuid",
"else": "$$REMOVE"
}
}
}
}
},
{
"$project": {
"_id": 0,
"uuid": "$_id",
"name": 1,
"jobUuid": {
"$ifNull": [{
"$arrayElemAt": [
"$jobUuids",
0
]
},
"default"
]
}
}
}]
答案 2 :(得分:0)
我能够通过以下汇总查询解决此问题,
我们首先要提取仅与用户提供的jobUuid
或“匹配”部分中的"default"
匹配的结果。
然后将结果基于uuid进行分组,并使用分组阶段,并且我们也在对结果进行计数。
首先使用replaceRoot
中的条件,我们正在检查分组文档的长度,
如果分组文档的长度大于或等于2,则为 过滤与提供的jobUuid相匹配的文档。
如果它小于或等于1,那么我们正在检查它是否与default
jobUuid匹配并返回它。
查询如下:
[
{
$match: {
$or: [{ jobUuid:1 },{ jobUuid: 'default'}]
}
},
{
$group: {
_id: '$uuid',
count: {
$sum: 1
},
docs: {
$push: '$$ROOT'
}
}
},
{
$replaceRoot: {
newRoot: {
$cond: {
if: {
$gte: [
'$count',
2
]
},
then: {
$arrayElemAt: [
{
$filter: {
input: '$docs',
as: 'item',
cond: {
$ne: [
'$$item.jobUuid',
'default'
]
}
}
},
0
]
},
else: {
$arrayElemAt: [
{
$filter: {
input: '$docs',
as: 'item',
cond: {
$eq: [
'$$item.jobUuid',
'default'
]
}
}
},
0
]
}
}
}
}
}
]