#python #mongodb #pandas #pymongo
#python #mongodb #панды #pymongo
Вопрос:
Я запрашиваю коллекцию, используя 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'}])
…но это не возвращает никаких данных.
Ответ №1:
Решение
Первая проблема с моей логикой заключалась в том, что line
был массивом, поэтому его нужно было сначала размотать.
Объединение этого с двумя $project
шагами и финалом $unwind
в конечном массиве выравнивает данные, чтобы получить (_id, shortDescription)
пары, которые можно быстро преобразовать в фрейм данных pandas:
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