【问题标题】:Using mongodb aggregate to match documents and get all values for a field使用 mongodb 聚合匹配文档并获取字段的所有值
【发布时间】:2017-04-08 03:32:40
【问题描述】:

在 Mongo 3.4 中

我有一个包含以下格式的文档的集合:

类型1:

{
"Level1": {
    "@version": "genR",
    "@revision": "aux",
    "Level2": {
        "container": {
            "type": "ARRAY",
            "categories": [
                {
                    "category": [
                        {
                            "Type": "STRING",
                            "Value": "Currency"
                        },
                        {
                            "Type": "STRING",
                            "Value": "EUR"
                        }
                    ]
                },
                {
                    "category": [
                        {
                            "Type": "STRING",
                            "Value": "Portfolio"
                        },
                        {
                            "Type": "STRING",
                            "Value": "ABCDEF"
                        }
                    ]
                },
             ]
          }
      }
  }
}

类型 2:

 {
"Level1": {
    "@version": "genR",
    "@revision": "aux",
    "Level2": {
        "container": {
            "type": "ARRAY",
            "categories": [
                {
                    "category": [
                        {
                            "Type": "STRING",
                            "Value": "Currency"
                        },
                        {
                            "Type": "STRING",
                            "Value": "EUR"
                        }
                    ]
                },
                {
                    "category": [
                        {
                            "Type": "STRING",
                            "Value": "Portfolio"
                        },
                        {
                            "Type": "STRING",
                            "Value": "ABCDEF"
                        }
                    ]
                },
                {
                    "category": [
                        {
                            "Type": "STRING",
                            "Value": "Short Description"
                        },
                        {
                            "Type": "STRING",
                            "Value": "Cash Only"
                        }
                    ]
                },
             ]
          }
      }
  }
}

如何编写汇总语句,以便仅从 Portfolio 与某个值匹配的文档中获取所有货币值。

我一直在使用pymongo的聚合框架如下:

pipeline = [{"$unwind":"$Level1.Level2.container.categories"},{"$unwind":"$Level1.Level2.container.categories.category"},{"$match":{"Level1.Level2.container.categories.category.Value":"Portfolio"}}]
pprint(db.command('aggregate',collection,pipeline=pipeline))

但没有结果。 Pymongo 有点混乱。即使有人能指出一般的方法,它也会有帮助。

假设 4 个匹配文档(每个文档具有不同数量的类别项)的预期响应是:

{'Currency': [{'Level1': {'Level2': {'container': {'categories': {'category': {'Value': 'EUR'}}}}}},
          {'Level1': {'Level2': {'container': {'categories': {'category': {'Value': 'EUR'}}}}}},
          {'Level1': {'Level2': {'container': {'categories': {'category': {'Value': 'USD'}}}}}},
          {'Level1': {'Level2': {'container': {'categories': {'category': {'Value': 'EUR'}}}}}}]}

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    您的结构并不理想,但您可以使用以下查询。

    下面$match阶段$ands的两个条件。在categories ($elemMatch) 数组下的category 数组($elemMatch) 中查找同时满足($all) Portfolio 与ABCDEF 值条件匹配的元素,然后是具有Currrency 值条件的元素的条件.

    $unwind 阶段是分解categories 后跟$match 以保留Currency category 嵌入的数组文档。

    $unwind 阶段是分解category 后跟$match 以删除Currency Value 嵌入文档。

    最后两个阶段是将$group+$push剩余的数据放入嵌入数组和$projectCurrency的值。

    您可以一次运行一个阶段以查看中间输出以便更好地理解。

    db.collection.aggregate( 
       { $match : 
           {  $and : 
                [
                  { "Level1.Level2.container.categories": 
                     { $elemMatch: 
                       { "category": 
                          { $all: 
                             [ 
                                { $elemMatch : { "Type": "STRING", "Value": "Portfolio" } },
                                { $elemMatch : { "Type": "STRING", "Value": "ABCDEF" } } 
                             ] 
                            } 
                         }
                       }
                   }, 
                   { "Level1.Level2.container.categories": 
                      { $elemMatch: 
                         { "category":
                             { $elemMatch : { "Type": "STRING", "Value": "Currency" } } 
                          } 
                       }
                   }
               ] 
           }
       },
      { $unwind : "$Level1.Level2.container.categories" },
      { $match : { "Level1.Level2.container.categories.category.Value": "Currency" } },
      { $unwind : "$Level1.Level2.container.categories.category" },
      { $match : { "Level1.Level2.container.categories.category.Value": { $ne : "Currency" } } },
      { $group: { _id: null, "Currency": { $push: "$$ROOT" } } }, 
      { $project: { _id: 0, "Currency.Level1.Level2.container.categories.category.Value": 1 } } )
    

    【讨论】:

    • 这给了我除了投资组合之外的所有类别。但是你给我指出了正确的方向。我会尽快更新评论。谢谢
    • Np。请添加预期的 json 响应,并将相应地调整查询。
    • 我有其他文档,除了“投资组合”和“货币”之外,还有其他“类别”字段。此类别子结构根据文档类型是动态的。
    • 还编辑了我的原始问题,以显示具有更多类别和预期响应的另一种文档类型
    • 感谢您添加所有详细信息。更新了答案。
    猜你喜欢
    • 2019-01-17
    • 2021-08-08
    • 2018-06-13
    • 2021-02-27
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    相关资源
    最近更新 更多