【问题标题】:Tabulate deeply nested MongoDB collection using PyMongo使用 PyMongo 对深度嵌套的 MongoDB 集合进行制表
【发布时间】:2019-09-14 01:47:42
【问题描述】:

我正在使用 pymongo 查询一个集合:

import pymongo

client = pymongo.MongoClient('0.0.0.0', 27017)
db = client.documents
collection = db.collections
test_data = collection.find_one({'metadata.encodingStage.terms.data.line.data.account.shortDescription': {'$exists': True}}, 
{'metadata.encodingStage.terms.data.line.data.account.shortDescription': 1})

我在这里使用find_one 进行说明,但实际上这是对整个集合的find 查询。

这给出了以下输出:

{'_id': ObjectId('5a2fb9371de46756df51f37b'),
 'metadata': {'encodingStage': {'terms': {'data':
    {'line': [{'data': {'account': {'shortDescription': ['123456']}}},
              {'data': {'account': {'shortDescription': ['7890123']}}}]}}}}}

但是,我想要表格格式的数据,按照 SQL 或 Pandas:

                               _id    shortDescription
-------------------------------------------------------
ObjectId('5a2fb9371de46756df51f37b')            123456
ObjectId('5a2fb9371de46756df51f37b')           7890123

我了解如何在 Python 中执行此操作,循环遍历结果,但为了计算效率,我希望更多的制表在 Mongo 中发生。

有没有一种简单的方法可以使用 pymongo 将结果输出为{'_id': 'XXX', 'shortDescription': 'XXX') 对,可以有效地制表?

展开聚合?

我已尝试将其作为 $unwind 聚合:

unwind = collection.aggregate([{'$unwind': '$metadata.encodingStage.terms.data.line.data.account.shortDescription'}])

...但这不会返回任何数据。

【问题讨论】:

    标签: python mongodb pandas pymongo


    【解决方案1】:

    解决方案

    我的逻辑的第一个问题是line 是一个数组,因此需要先展开。

    将其与叶数组上的两个$project 步骤和最后一个$unwind 相结合,可以将数据展平以提供可以快速转换为pandas DataFrame 的(_id, shortDescription) 对:

    db.collection.aggregate([
                               {"$project": {"line": "$metadata.encodingStage.terms.data.line"}},
                               {"$unwind": "$line"},
                               {"$project": {"shortDescription": "$line.data.account.shortDescription"}},
                               {"$unwind": "$shortDescription"}
                            ])
    

    输出:

    [{'_id': ObjectId('xxxxxxxxxxxxxxx123'), 'shortDescription': '12340000'},
     {'_id': ObjectId('xxxxxxxxxxxxxxx123'), 'shortDescription': '43210000'},
     {'_id': ObjectId('yyyyyyyyyyyyyyy789'), 'shortDescription': '56780000'},
     {'_id': ObjectId('yyyyyyyyyyyyyyy789'), 'shortDescription': '78920000'},
     {'_id': ObjectId('yyyyyyyyyyyyyyy789'), 'shortDescription': '55550000'}]
    

    无需额外转换即可在 pandas 中加载:

    import pandas as pd
    results = db.collection.aggregate([
                               {"$project": {"line": "$metadata.encodingStage.terms.data.line"}},
                               {"$unwind": "$line"},
                               {"$project": {"shortDescription": "$line.data.account.shortDescription"}},
                               {"$unwind": "$shortDescription"}
                            ])
    df = pd.DataFrame([item for item in results])
    

    输出:

    print(df)
    
                      _id shortDescription
    0  xxxxxxxxxxxxxxx123         12340000
    1  xxxxxxxxxxxxxxx123         43210000
    2  yyyyyyyyyyyyyyy789         56780000
    3  yyyyyyyyyyyyyyy789         78920000
    4  yyyyyyyyyyyyyyy789         55550000
    

    【讨论】:

      猜你喜欢
      • 2021-12-05
      • 1970-01-01
      • 2021-01-18
      • 1970-01-01
      • 1970-01-01
      • 2018-11-17
      • 1970-01-01
      • 2020-07-21
      • 2011-03-10
      相关资源
      最近更新 更多