Почему MongoDB update () медленнее, чем find (), если ни один документ не сопоставлен, и это можно изменить? - PullRequest
0 голосов
/ 15 июня 2019

Рассмотрим следующие два подхода (возможно) обновления группы записей:

Подход 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, было бы скуднее ...

1 Ответ

0 голосов
/ 16 июня 2019

Это в JS?db.getCollection("users").find( выглядит так, как будто оно должно вернуть Обещание, а обещания не имеют длины, поэтому код обновления с кодом ids.length никогда не запустится.

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