【问题标题】:MongoDB nested object aggregation countingMongoDB嵌套对象聚合计数
【发布时间】:2015-03-10 23:37:48
【问题描述】:

我有一个高度嵌套的 mongoDB 对象集,我想计算与给定条件匹配的子文档的数量编辑:(在每个文档中)。例如:

{"_id":{"chr":"20","pos":"14371","ref":"A","alt":"G"},
"studies":[
    {
        "study_id":"Study1",
        "samples":[
            {
                "sample_id":"NA00001",
                "formatdata":[
                    {"GT":"1|0","GQ":48,"DP":8,"HQ":[51,51]}
                ]
            },
            {
                "sample_id":"NA00002",
                "formatdata":[
                    {"GT":"0|0","GQ":48,"DP":8,"HQ":[51,51]}
                ]
            }
        ]
    }
]
}
{"_id":{"chr":"20","pos":"14372","ref":"T","alt":"AA"},
"studies":[
    {
        "study_id":"Study3",
        "samples":[
            {
                "sample_id":"SAMPLE1",
                "formatdata":[
                    {"GT":"1|0","GQ":48,"DP":8,"HQ":[51,51]}
                ]
            },
            {
                "sample_id":"SAMPLE2",
                "formatdata":[
                    {"GT":"1|0","GQ":48,"DP":8,"HQ":[51,51]}
                ]
            }
        ]
    }
]
}
{"_id":{"chr":"20","pos":"14373","ref":"C","alt":"A"},
"studies":[
    {
        "study_id":"Study3",
        "samples":[
            {
                "sample_id":"SAMPLE3",
                "formatdata":[
                    {"GT":"0|0","GQ":48,"DP":8,"HQ":[51,51]}
                ]
            },
            {
                "sample_id":"SAMPLE7",
                "formatdata":[
                    {"GT":"0|0","GQ":48,"DP":8,"HQ":[51,51]}
                ]
            }
        ]
    }
]
}

我想知道有多少子文档包含 GT:"1|0",在这种情况下,第一个文档为 1,第二个文档为 2,第三个文档为 0。我已经尝试过展开和聚合函数,但我显然没有做正确的事情。当我尝试按“GT”字段计算子文档时,mongo 抱怨:

db.collection.aggregate([{$group: {"$studies.samples.formatdata.GT":1,_id:0}}])

因为我的组名不能包含“.”,但如果我把它们排除在外:

db.collection.aggregate([{$group: {"$GT":1,_id:0}}])

它抱怨是因为“$GT 不能是操作员名称”

有什么想法吗?

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    在处理数组时需要处理$unwind,并且需要执行3次:

     db.collection.aggregate([
    
         // Un-wind the array's to access filtering 
         { "$unwind": "$studies" },
         { "$unwind": "$studies.samples" },
         { "$unwind": "$studies.samples.formdata" },
    
         // Group results to obtain the matched count per key
         { "$group": {
             "_id": "$studies.samples.formdata.GT",
             "count": { "$sum": 1 }
         }}
     ])
    

    理想情况下,您希望过滤输入。可能在处理 $unwind 之前和之后都使用 $match 执行此操作,并使用 $regex 匹配点处数据以“1”开头的文档。

     db.collection.aggregate([
    
         // Match first to exclude documents where this is not present in any array member
         { "$match": { "studies.samples.formdata.GT": /^1/ } },
    
         // Un-wind the array's to access filtering 
         { "$unwind": "$studies" },
         { "$unwind": "$studies.samples" },
         { "$unwind": "$studies.samples.formdata" },
    
         // Match to filter
         { "$match": { "studies.samples.formdata.GT": /^1/ } },
    
         // Group results to obtain the matched count per key
         { "$group": {
             "_id": {
                  "_id": "$_id",
                  "key": "$studies.samples.formdata.GT"
             },
             "count": { "$sum": 1 }
         }}
     ])
    

    请注意,在所有情况下,以“美元 $”为前缀的条目都是指文档属性的“变量”。这些是使用右侧输入的“值”。左侧的“keys”必须指定为纯字符串键。没有变量可以用来命名键。

    【讨论】:

    • 是的,这可行,但它实际上计算集合中的所有值,而不是文档。我正在寻找的是相当于计算每个文档中的子文档,包括是否有 0。我将编辑我的原始帖子以使其更加清晰。
    • @StevenHart 你的问题不清楚。但是在分组键中包含文档 ID 是一件简单的事情。查看变化。
    • $unwinds 之后是否需要第二个 $match?
    【解决方案2】:

    https://mongoplayground.net/p/DpX6cFhR_mm

    db.collection.aggregate([
      {
        "$unwind": "$tags"
      },
      {
        "$match": {
          "$or": [
            {
              "tags.name": "Canada"
            },
            {
              "tags.name": "ABC"
            }
          ]
        }
      },
      {
        "$group": {
          "_id": null,
          "count": {
            "$sum": 1
          }
        }
      }
    ])
    

    【讨论】:

      猜你喜欢
      • 2021-02-13
      • 2020-01-24
      • 2020-04-23
      • 2018-09-10
      • 2017-07-26
      • 2020-11-09
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多