簡體   English   中英

如何在MongoDB中找到大於文檔大小的數組

[英]How to find array greater than document size in MongoDB

我有如下架構

[
{
 id:"111"
 tags:[222,333,444,555]
},
{
 id: "222"
 tags:[312,345,534]
},
{
 id:"333"
 tags:[111,222,333,444,555]
},

]

我想在聚合管道中找到標簽數組大小大於$match返回的文檔大小的所有文檔,因此在上面的示例中。 文檔數為 3,所以我想返回所有標簽數組大小大於 3 的文檔

[
{
 id:"111"
 tags:[222,333,444,555]
},
{
 id:"333"
 tags:[111,222,333,444,555]
},

]

我正在使用聚合管道來處理其他信息,我被困在如何存儲文檔大小以便我可以找到所有大於文檔大小的標簽

下面是我正在使用的查詢,我想在聚合和一次調用中進行

.aggregate([
        
   {
      "$match":{
         "ids":{
            "$in":[
               "111",
               "222",
                "333"
            ]
         }
      }
   })]

Facet 幫你解決這個問題。

  • $facet有助於對傳入的文檔進行分類。 我們使用totalDoc計數的文件和allDocuments用於獲取所有的文件
  • $arrayElemAt有助於從totalDoc中獲取第一個對象,我們已經知道在totalDoc應該只有一個對象。 因為我們分組的時候用的是_id:null
  • $unwind有助於allDocuments數組

這是代碼

db.collection.aggregate([
  {
    $facet: {
      totalDoc: [
        {
          $group: {
            _id: null,
            count: {
              $sum: 1
            }
          }
        }
      ],
      allDocuments: [
        {
          $project: {
            tags: 1
          }
        }
      ]
    }
  },
  {
    $addFields: {
      totalDoc: {
        "$arrayElemAt": [
          "$totalDoc",
          0
        ]
      }
    }
  },
  {
    $unwind: "$allDocuments"
  },
  {
    $addFields: {
      sizeGtDoc: {
        $gt: [
          {
            $size: "$allDocuments.tags"
          },
          "$totalDoc.count"
        ]
      }
    }
  },
  {
    $match: {
      sizeGtDoc: true
    }
  },
  {
    "$replaceRoot": {
      "newRoot": "$allDocuments"
    }
  }
])

工作Mongo 游樂場

您可以使用$facet來獲得兩個流,即一個帶有過濾文檔的流和使用$count 然后可以使用$filter進一步聚合生成的流,如下所示以獲得所需的結果

db.getCollection('collection').aggregate([
    { '$facet': {
        'counts': [
            { '$match': { 'id': { '$in': ['111', '222', '333'] } } }, 
            { '$count': "numberOfMatches" }
        ],
        'docs': [
            { '$match': { 'id': { '$in': ['111', '222', '333'] } } }, 
        ]  
    } },
    {  '$project': {
        'result': {
            '$filter': {
                'input': '$docs',
                'cond': {
                    '$gt': [
                        { '$size': '$$this.tags' },
                        { '$arrayElemAt': ['$counts.numberOfMatches', 0] }
                    ]
                }
            }
        } 
    } }
])

你可以試試,

  • $match你的條件
  • $group by null 並創建文檔的root數組並在 count 中獲取根文檔的count
  • $unwind解構root數組
  • $match tags大小和count大於或不使用$expr表達式匹配
  • $replaceRoot替換root對象
db.collection.aggregate([
  { $match: { id: { $in: ["111", "222", "333"] } } },
  {
    $group: {
      _id: null,
      root: { $push: "$$ROOT" },
      count: { $sum: 1 }
    }
  },
  { $unwind: "$root" },
  { $match: { $expr: { $gt: [{ $size: "$root.tags" }, "$count"] } } },
  { $replaceRoot: { newRoot: "$root" } }
])

操場


第二種選擇:

  • 前兩個階段$match$group都與上面的查詢相同,
  • $project過濾根數組匹配條件,如果tags大小和count大於或不大於,這將返回過濾后的根數組
  • $unwind解構根數組
  • $replaceRoot將根對象替換為根
db.collection.aggregate([
  { $match: { id: { $in: ["111", "222", "333"] } } },
  {
    $group: {
      _id: null,
      root: { $push: "$$ROOT" },
      count: { $sum: 1 }
    }
  },
  {
    $project: {
      root: {
        $filter: {
          input: "$root",
          cond: { $gt: [{ $size: "$$this.tags" }, "$count"] }
        }
      }
    }
  },
  { $unwind: "$root" },
  { $replaceRoot: { newRoot: "$root" } }
])

操場

如果需要,您可以跳過$unwind$replaceRoot階段,因為此查詢始終以根目錄返回一個文檔,因此您可以輕松訪問像這樣的result[0]['root'] ,您可以節省 2 個階段的處理和執行時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM