Проблема с производительностью MongoDB, возможно, из-за игнорирования проекции в проекте NodeJS с использованием собственного драйвера MongoDB - PullRequest
1 голос
/ 29 февраля 2020

Длинная версия: (Прокрутите вниз для TLDR)

У меня есть коллекция "библиотек". Библиотека может иметь тип "шаблон" или "стандартный шаблон" (в этом сценарии). Если он принадлежит организации, он будет содержать «organization_id» (который в противном случае равен нулю), если он не принадлежит, но организация имеет к нему доступ, этот идентификатор будет добавлен в массив «организаций». Библиотеки с типом "template" всегда принадлежат, а библиотеки с типом "standard-template" никогда не принадлежат. Запрос для этого выглядит следующим образом:

{
    "$or": [{
        "organization_id": id,
        "type": "template"
    }, {
        "organization_id": null,
        "type": "standard-template",
        "organizations": id
    }]
}

У меня есть индекс типа {"organization_id": 1, "type": 1} и не так много библиотек "стандартных шаблонов". Объяснение скажет мне, что выполнение этого запроса занимает + - 4 мс и возвращает 50 документов.

В моем приложении NodeJS это займет около 12 секунд. Вероятно, это связано с размером каждого документа (который может варьироваться от нескольких КБ до 10 МБ).

Я пытаюсь ограничить это с помощью проекции, чтобы получать только соответствующие поля, однако, похоже, это быть полностью проигнорированным. Я испробовал все варианты приведенного ниже кода, но, похоже, ни один из них не помог.

TLDR

Значение проекции в моем коде, похоже, игнорируется , В этом примере я пытаюсь получить только поля "_id", но в итоге получаю документы целиком.

Код, используемый для тестирования

let id = ObjectID('5e56503cafc87b893b92827c');
let start = performance.now();
let find = mongodb.collection('libraries').find(
    {
        "$or": [
            {"organization_id": id, "type": "template"},
            {"organization_id": null,"type": "standard-template", "organizations": id}
        ]
    }, {_id: 1});

while (await find.hasNext()) {
    const doc = await find.next();
    console.log(doc); //HUGE! way more than just _id!
}

console.log(performance.now() - start); //about 12000 ms

Еще более короткий тестовый код :

console.log(await mongodb.collection('libraries').findOne({}, {_id: 1})); //HUGE!

В любых примерах или документах, которые я нашел, это делается, по-видимому, одинаково. Я уверен, что делал это в прошлом. Я что-то наблюдаю? Любые идеи очень ценятся.

1 Ответ

1 голос
/ 29 февраля 2020

Поскольку вы используете курсор для итерации записей, вам нужно связать функцию проекта для применения проекции. То, как вы делаете, игнорирует проекцию. Ваш код должен выглядеть следующим образом:

et id = ObjectID('5e56503cafc87b893b92827c');
let start = performance.now();
let find = mongodb.collection('libraries').find(
    {
        "$or": [
            {"organization_id": id, "type": "template"},
            {"organization_id": null,"type": "standard-template", "organizations": id}
        ]
    }).project({_id: 1}); // this is the projection

while (await find.hasNext()) {
    const doc = await find.next();
    console.log(doc); //HUGE! way more than just _id!
}

console.log(performance.now() - start); //about 12000 ms

ИЛИ

. Вы можете заключить проекцию в свойство проекции, например,

{"projection": {"_id": 1}}

. Любое из этих действий должно работать.

...