Кеширование результатов агрегации Mongodb

У меня довольно большая коллекция в mongodb примерно с 100 000 документов (не шарнирных). Это серверная часть для веб-приложения, которая в основном просто позволяет пользователю просматривать разные способы просмотра одной и той же информации в этой коллекции.

Для одного из представлений я пытаюсь подсчитать количество вхождений поля, используя структуру агрегирования. Это означает агрегирование всей коллекции. Проблема в том, что эта операция агрегирования (которая представляет собой простой конвейер групп, сортировки и ограничения) занимает 2 секунды, что слишком медленно для веб-приложения.

Итак, мой вопрос: каково предпочтительное решение для кэширования результата этой операции агрегирования? Насколько я обнаружил, невозможно «объединить» в новую коллекцию или что-то в этом роде. На данный момент единственное решение, которое я нашел, - это прочитать весь результат в переменной, а затем вставить эту переменную в новую коллекцию с помощью вставки, но я боюсь, что это связано с отправкой большого количества данных из базы данных => в мое приложение => вернуться к базе данных?

Какие-либо предложения?

Пример трубопровода:

res = items.aggregate([
    { "$group": { "_id": { "item_id": "$item_id", "title": "$title", "category": "$category" }, "count": { "$sum": 1 } } },
    { "$sort": { "count": -1 } },
    { "$limit": 5 }
])

Схема - это в основном эти 3 поля + еще несколько, которые действительно не актуальны, а именно:

doc = {
    "item_id": 1000,
    "title": "this is the item title",
    "category": "this is the item category"
}

Я безуспешно пробовал индексировать как item_id, так и все 3 поля.


person agnsaft    schedule 01.02.2013    source источник
comment
Может быть, было бы полезно, если бы вы могли предоставить пример структуры ваших документов и этапов вашего конвейера агрегации. Вы пользуетесь индексами?   -  person attish    schedule 01.02.2013


Ответы (1)


Агрегация возвращает результат в один документ. Результат ограничен 16М. Документ возвращается в приложение.

Если вы хотите «агрегировать» в коллекцию - используйте map-reduce.

map_function = function () {
        emit(this.item_id, {"item_id": this.item_id, /* any other info */ "count": 1});
};

reduce_function = function (key, values) {
        var result = {"item_id": key, /* any other info should be given from one or any of values array objects */ "count": 0};
        values.forEach(function (value) {
                result["count"] += value["count"];
        });
        return result;
};

Не уверен, можно ли передавать структурные значения - попробуйте. Ключевое поле, испускающее BTW, - это хорошо.

person Vitaly Greck    schedule 04.02.2013