mongo 根据条件聚合来过滤文档以进行版本控制

我正在研究版本控制,我们有基于UUIDs和 的文档jobUuidsjobUuids是与当前工作用户关联的文档。我对这些集合有一些聚合查询,需要根据作业 UUID 进行更新,

聚合查询获取的结果应该是这样的:

  • 如果当前用户jobUuid文档不存在,则jobUuid: "default"返回主文档(没有任何jobUuid的文档),

  • 如果作业 uuid 存在,则仅返回文档。

我有一个$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一些与此处不相关但在最后需要的字段(对于那些想要在所有内容上使用投影的人提及这一点)田野)。


胡子哥哥
浏览 143回答 3
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"}}]此处示例 - https://mongoplayground.net/p/KrL-1s8WCpw

四季花海

这是我要做的:匹配阶段使用 $in 而不是 $or (为了可读性)小组赛阶段使用 $uuid 上的 _id,就像您所做的那样,但不要将所有数据推送到数组中,而是更具选择性。_id 已经存储了 $uuid,因此没有理由再次捕获它。每个 $uuid 的名称必须始终相同,因此仅采用第一个实例。根据匹配,jobUuid 只有两种可能性,但这将假设它将是“默认”或其他内容,并且可能会出现多次非“默认”jobUuid。使用“$addToSet”而不是推送到数组,以防用户多次出现相同的 jobUuid,此外,在添加到集合之前,使用条件仅添加非“默认”jobUuid,使用 $$REMOVE以避免在 jobUuid 为“默认”时插入 null。最后,“$project”来清理一切。如果 jobUuids 数组的元素 0 不存在(为 null),则该用户除了 jobUuid 为“默认”之外没有其他可能性,因此使用“$ifNull”进行测试并根据需要设置“默认”。这里可能有超过 1 个 jobUuid,具体取决于您的数据库/应用程序是否允许,由您决定如何处理(取最高的、取最低的等)。测试于: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"            ]        }    }}]

慕尼黑的夜晚无繁华

我能够通过以下聚合查询解决这个问题,jobUuid我们首先提取仅与用户提供的或"default"匹配部分中的匹配的结果。然后,使用小组赛阶段根据 uuid 对结果进行分组,并且我们也会对结果进行计数。使用首先的条件,replaceRoot我们检查分组文档的长度,如果分组文档长度大于或等于 2,我们将过滤与提供的 jobUuid 匹配的文档。如果它小于或等于 1,那么我们将检查它是否与 jobUuid 匹配default并返回它。查询如下:[    {      $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              ]            }          }        }      }    }  ]
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript