#mongodb #pymongo
#mongodb #pymongo
Вопрос:
Я не очень хорошо разбираюсь во всех вещах MongoDB, но я сталкиваюсь с проблемой, на которую я изо всех сил пытаюсь найти ответ (документы не всегда понятны).
По сути, у меня есть большая коллекция документов с таким типом структуры:
{'addr': 'x@a.com', 'rep': 2, ... } // there are 100s of fields
{'addr': 'x@b.com', 'rep': 2, ... }
{'addr': 'x@c.com', 'rep': 2, ... }
{'addr': 'x@a.com', 'rep': 2, ... }
{'addr': 'x@b.com', 'rep': 2, ... }
{'addr': 'x@c.com', 'rep': 2, ... }
Затем, что я хочу сделать, это сгруппировать по addr, пример, скажем, максимум 1000 из каждой группы, затем вывести все документы в pymongo.
Сейчас у меня есть что-то вроде
aggs = mongo['db'].db.data['collection1'].aggregate([{'$group': {'_id': '$addr'}}, {'$sample': {'size': 10}}])
Я видел, что могу использовать project для вывода всех полей (я думаю), но есть ли способ получить доступ к результатам каждой агрегации, чтобы я мог сделать что-то вроде:
for agg in aggs:
for result in agg.results:
print(result)
Комментарии:
1. Итак, вы хотите распечатать результат с каждого этапа?
Ответ №1:
Ты не можешь на самом деле сделать это вот так. После $group
этого вам нужно указать, как вы хотите агрегировать любые поля для проецирования, так что вы потеряете желаемое разрешение. Я бы предпочел, чтобы все было просто и делалось в два прыжка. Один, чтобы получить список отдельных addr
групп, а затем выполнить выборку для каждой группы; что-то вроде:
addrs = db.collection1.distinct('addr')
for addr in addrs:
aggs = db.collection1.aggregate([{'$match': {'addr': addr}},
{'$sample': {'size': 10}}])
for agg in aggs:
print(f'{addr}, {agg}')
Комментарии:
1. Да, действительно, именно так я это делаю сейчас, но это очень медленно: (
2. Ну, вы вряд ли улучшите производительность, используя агрегированный запрос. Проблема
$sample
в том, что это просто медленно. У вас есть индексaddr
?3. 🙁 Я добавил индекс в addr и перебираю каждый из адресов, которые имеют более X вхождений. `aggs = db.collection1.aggregate([{‘$group’: {‘_id’: ‘$addr’, ‘num_records’: {‘$sum’: 1}}}, {‘$ совпадение’: {‘num_records’: {‘$gte’: 50}}}]) для agg в aggs: _agg_docs = db.collection1.find({‘addr’: agg[‘_id’]}).limit(1000) docs = [doc для doc в _agg_docs] ` Это нормально 🙂