$ sum внутри агрегата в mongomock, похоже, не работает - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть совокупный запрос Монго, который проецирует некоторые поля и вычисляет два других, используя $ sum .Запрос работает, как и ожидалось, поэтому я создал для него модульный тест, и, к моему удивлению, тест не удался.

Я создал минимальный, полный и проверяемый пример , чтобы проверить свою гипотезучто это проблема с MongoMock, и похоже, что это!

Вот код:

import mongoengine as mongo
from mongoengine import connect
from mongoengine.queryset import QuerySet

class ValuesList(mongo.EmbeddedDocument):
    updated_value = mongo.DecimalField()


class ValuesHistory(mongo.Document):
    name = mongo.StringField()
    base_value = mongo.DecimalField()
    values_list = mongo.EmbeddedDocumentListField(ValuesList, required=False)
    meta = {
        'collection' : 'values_history'
    }

    def __str__(self):
        return 'name: {}\nbase_value: {}\n'.format(self.name, self.base_value)


def migrate_data(new_collection):
    ValuesHistory.objects.aggregate(
        {'$project': {'name': 1,
                     'base_value': {'$sum': ['$base_value', {'$arrayElemAt': ['$values_list.updated_value', -1]}]}
                      }
        },
        {'$out': "{}".format(new_collection)}
    )


def clear_tables_and_insert_test_data(db):
    db.test.values_history.drop()
    db.test.updated_values.drop()
    ValuesHistory(name='first',
                  base_value=100,
                  values_list=[ValuesList(updated_value=5),
                               ValuesList(updated_value=15)]).save()

def run_aggregate_query_with_db(db):
    new_collection_name = 'updated_values'

    migrate_data(new_collection_name)

    new_group = ValuesHistory.switch_collection(ValuesHistory(), new_collection_name)
    aggregated_values = QuerySet(ValuesHistory, new_group._get_collection()).all()
    for value in aggregated_values:
        print(value)

    db.close()

Краткое объяснение кода выше.

ValuesHistory - это класс, который содержит String name , числовой base_value и список значений ( ValuesList class).

Метод clear_tables_and_insert_test_data очищает две таблицы, использованные в этом тесте, и вставляет некоторые данные теста.

Запрос в методе migrate_data создает новую коллекцию(через оператор $ out ) и base_value вновь созданной коллекции должны быть суммой текущего значения и последнего значения в списке values_list .В моем случае это должно быть 115 (равное 100 текущему значению и 15 последним значениям в списке).

Если я запускаю код, используя соединение с моей локальной MongoDB, например:

if __name__ == '__main__':
    db = connect('test') # connect to real instance of Mongo
    clear_tables_and_insert_test_data(db)
    run_aggregate_query_with_db(db)

В результате я получаю 115, что соответствует ожидаемому.

Если вместо этого я использую соединение с MongoMock:

if __name__ == '__main__':
    db = connect('test', host='mongomock://localhost') # Connect to MongoMock instance
    clear_tables_and_insert_test_data(db)
    run_aggregate_query_with_db(db)

В результате я получаю 100,что странно!Похоже, оператор $ sum не выполнил свою работу должным образом, так как сумма 100 и 15 привела к 100!

EDIT : я также пытался использовать $ add оператор, но проблема остается той же, возвращая 100, когда должно быть 115.

TL; DR;

Вопрос: Как мне использовать $ sum (или $ add ) внутри агрегатного конвейера в MongoMock, чтобы он давал правильное значение?

1 Ответ

0 голосов
/ 22 февраля 2019

Описанная проблема действительно была ошибкой в ​​Mongomock, существовавшей до версии 3.14.0.

После публикации исходного вопроса я открыл проблему в github Mongomock, описывающуюэта проблема.Вскоре после того, как это было исправлено, и версия 3.15.0 была выпущена несколько дней назад.Я запустил код вопроса и теперь проблема решена для операторов $ add и $ sum !

TL; DR

Для решения проблемы достаточно обновить Mongomock 3.15.0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...