->field('extra.targetPlayerId')->exists(FALSE)
Правильно, что это, вероятно, самое большое препятствие для ускорения запроса.
из документов :
До версии 2.0, $ exist не может использовать индекс. Индексы по другим полям все еще используются.
$ существует не очень эффективно даже с индексом , и особенно. с {$ Существует: истина}, поскольку он будет эффективно сканировать все проиндексированные значения.
Возможно, рассмотрите возможность добавления логического поля таким образом, чтобы вы могли проверять наличие истинного / ложного, а не существующего, и включить это поле в индекс.
Или даже переместить это конкретное условие в функцию карты:
function() {
var total = 0;
if (!this.extra || !this.extra.targetPlayerId) {
return; //bail - count nothing
}
if (this.comments) {
total += this.comments.length;
}
if (this.likes) {
total += this.likes.length;
}
if (total > 0) {
emit(this.playerId, total);
}
}
Индексирование не является черно-белым ответом, например, если у вас много данных:
{
time: 1,
permission: 1,
extra.hasTargetPlayer: 1
}
, вероятно, будет работать достаточно хорошо - поскольку это позволит монго сосредоточиться на правильном диапазоне дат в качестве первого критерия.
Кроме того, может быть более уместным просто изменить схему данных. Вы сохраняете результат этого запроса?
т.е. запросить один раз и сохранить результат, так что для любых последующих запросов вы можете просто сделать:
db.appstats.findOne({_id: "201152"})
где _id - год и номер недели. Если вы генерируете статистику по неделям, каждую неделю - вы можете выполнять тяжелый запрос по расписанию (cron), и поэтому на скорость запроса пользователей не влияет фактический расчет результатов.