亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

mongo 根據條件聚合來過濾文檔以進行版本控制

mongo 根據條件聚合來過濾文檔以進行版本控制

胡子哥哥 2023-07-20 16:11:59
我正在研究版本控制,我們有基于UUIDs和 的文檔jobUuids,jobUuids是與當前工作用戶關聯的文檔。我對這些集合有一些聚合查詢,需要根據作業 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一些與此處不相關但在最后需要的字段(對于那些想要在所有內容上使用投影的人提及這一點)田野)。
查看完整描述

3 回答

?
侃侃無極

TA貢獻2051條經驗 獲得超10個贊

根據評論更新:


但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


查看完整回答
反對 回復 2023-07-20
?
四季花海

TA貢獻1811條經驗 獲得超5個贊

這是我要做的:

  1. 匹配階段使用 $in 而不是 $or (為了可讀性)

  2. 小組賽階段使用 $uuid 上的 _id,就像您所做的那樣,但不要將所有數據推送到數組中,而是更具選擇性。_id 已經存儲了 $uuid,因此沒有理由再次捕獲它。每個 $uuid 的名稱必須始終相同,因此僅采用第一個實例。根據匹配,jobUuid 只有兩種可能性,但這將假設它將是“默認”或其他內容,并且可能會出現多次非“默認”jobUuid。使用“$addToSet”而不是推送到數組,以防用戶多次出現相同的 jobUuid,此外,在添加到集合之前,使用條件僅添加非“默認”jobUuid,使用 $$REMOVE以避免在 jobUuid 為“默認”時插入 null。

  3. 最后,“$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"

            ]

        }

    }

}]


查看完整回答
反對 回復 2023-07-20
?
慕尼黑的夜晚無繁華

TA貢獻1864條經驗 獲得超6個贊

我能夠通過以下聚合查詢解決這個問題,

  • 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

              ]

            }

          }

        }

      }

    }

  ]


查看完整回答
反對 回復 2023-07-20
  • 3 回答
  • 0 關注
  • 187 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號