Рассмотрим следующие два подхода (возможно) обновления группы записей:
Подход 1 («найди и возможно обнови»):
let ids = db.getCollection("users").find({
"status.lastActivity": {"$lte": timeoutDate}
}, {
"fields": {"_id": 1}
}).fetch().map(doc => {
doc = doc._id;
return doc
});
if (ids.length) {
db.getCollection("users").update({
"_id": {"$in": ids}
}, {
"$set": {
"status.idle": true
}
}, {
"multi": true
});
}
Подход 2 («прямое обновление»):
db.getCollection("users").update({
"status.lastActivity": {"$lte": timeoutDate}
}, {
"$set": {
"status.idle": true
}
}, {
"multi": true
});
А теперь для простоты предположим, что никогда не бывает пользователей с status.lastActivity
меньшим, чем timeoutDate
(поэтому ids
также всегда является пустым массивом).
В этом случае я получаю значительно лучшую производительность с подходом 1. Подобный подход 1 занимает от 0,1 до 2 мс, а подход 2 - от 40 до 80 мс.
Мой вопрос сейчас такой: почему это так? Я бы предположил, что MongoDB достаточно «умен», чтобы делать что-то похожее на Подход 1 под капотом, когда я фактически использую Подход 2, и не тратить ресурсы, когда на самом деле нет записи, совпавшей с селектором ...
И можно ли как-то изменить его, чтобы он работал таким образом? Или у меня может быть какая-то неправильная конфигурация, которая вызывает это, и я мог бы избавиться? Потому что, очевидно, что писать вещи, как в подходе 2, было бы скуднее ...