Агрегация -> Образец -> Шаблон документов в MongoDB

#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] ` Это нормально 🙂