(py)返回按相关字段分组的匹配值的Mongo查询?

2024-09-30 22:18:34 发布

您现在位置:Python中文网/ 问答频道 /正文

(请随意重命名问题)

我在mongo收藏中有一些数据,看起来像:

{
    ...
    'tree_id': 'ABC123',
    'serial_id': 'XYZ789',
    ...
}

在一个json请求中,我得到了大量的序列id值(称之为wantedIDs)。我需要(用python)创建一个如下所示的字典:

{'tree_id_1': [...all the serial_ids that matched tree_id_1...],
 'tree_id_2': [...all the serial_ids that matched tree_id_2...],
 ...}

我可以这样做:

myMap = defaultdict(list)
for doc in client.database.collection.find({'serial_id': {'$in': wantedIDs}}):
    myMap[doc['tree_id']].append(doc['serial_id'])

我想知道是否有一个更Python或蒙哥里的方式来做这件事呢?我是pymongo的新手。我也很好奇$in在哪一点上不是我们要走的路,如果有的话。wantedIDs的列表可能相当大。你知道吗


Tags: the数据inidtreeidsdocthat
2条回答

I'm wondering if there is a more pythonic or mongorific way of doing this though?

是的,有。寻找MongoDB Aggregation Framework。Pymongo集合有一个aggregate方法,用于尝试执行的操作类型(请参阅update)。你知道吗

I'm also curious at what point the $in isn't the way to go, if ever.

嗯,我不完全确定$in,但我认为您可以将数据放在那里,直到达到BSON文档大小限制,即16兆字节。无论如何,我建议不要接近这个限制,因为它可能会减慢您的应用程序和MongoDB服务器的速度。你知道吗

更新

聚合无助于解决潜在的大问题。find使用的相同查询将位于聚合管道的$match操作符中,因此应用相同的限制。你知道吗

如果您检测到wantedIDs的列表太大,那么您可以做的一件事就是根本不按serial_id进行筛选,这可能是因为它会达到BSON限制,也可能是因为它会导致MongoDB扫描几乎整个集合。你知道吗

您还可以在MongoDB中执行单个聚合,将树id的整个映射引入到应用程序中,然后在Python代码中进行匹配。聚合的结果也不能超过BSON的最大文档大小。如果集合变化不大,则可以尝试缓存聚合结果以提高性能。你知道吗

当然,所有这些都可能是过早的优化。如果不知道收集/申请的细节,就很难判断。你知道吗

除此之外,如果不重新考虑应用程序或重新构造数据以完全避免$in,就没有什么可以做的了。你知道吗

聚合框架可以让您接近:

>>> db.collection.insert({'tree_id': 'ABC123', 'serial_id': 1})
ObjectId('52b105e3ca1ce9bb42202f63')
>>> db.collection.insert({'tree_id': 'ABC123', 'serial_id': 2})
ObjectId('52b105e4ca1ce9bb42202f64')
>>> db.collection.insert({'tree_id': '2', 'serial_id': 1})
ObjectId('52b105f8ca1ce9bb42202f65')
>>> db.collection.aggregate([{
    '$group': {
        '_id': '$tree_id',
        'serial_ids': {'$push': '$serial_id'}
     }
}])
{u'ok': 1.0,
    u'result': [{u'_id': u'2', u'serial_ids': [1]},
                {u'_id': u'ABC123', u'serial_ids': [1, 2]}
    ]
}

从这里开始,用Python完成:

dict([(row['_id'], row['serial_ids']) for row in result['result']])

相关问题 更多 >