Понимание неявного И в Мангусте/MongoDB

#mongodb #mongoose

Вопрос:

Я изо всех сил пытаюсь понять неявное И при использовании запятых в Mongoose/MongoDB.

Не вдаваясь в подробности того, что именно делает этот запрос, я попытаюсь дать простое объяснение того, что я пытаюсь понять.

Вот простая Post модель, в которой для моего вопроса требуется только соответствующее поле:

 const PostSchema = new Schema({
  likeCount: {
    type: Number,
    default: 0
  }
})
 

По сути, у меня есть три переменные для запроса. Я запрашиваю сообщения с likeCount числом между двумя числами, а затем больше, чем третье число.

Вот три примера переменных для запроса:

 var floor = 10, ceiling = 20, cursor = 0
 

Когда я пишу запрос с выражениями в таком порядке,

 Post.find({
  likeCount: {
    $gte: floor,
    $lte: ceiling,
    $gte: cursor
  }
})
 

Я ожидаю, что Post likeCount в результатах поиска будет пропущено все, что имеет значение 0, потому что в данном случае они будут отфильтрованы по первому выражению запроса $gte: 10 . Вместо этого я получаю неправильные результаты, например, a Post с likeCount включенным значением 0.

Однако, когда я просто меняю порядок выражений, вот так:

 Post.find({
  likeCount: {
    $gte: cursor
    $gte: floor,
    $lte: ceiling,
  }
})
 

Затем я начинаю получать правильные результаты. Мой вопрос в том, почему это происходит? Из моего понимания документации следует, что при работе И в MongoDB возникает эффект короткого замыкания. Почему имеет значение, что выражения расположены в определенном порядке? Если поле документа не передает одно из выражений, независимо от того, в каком порядке, не следует ли исключить этот документ из результатов?

Ответ №1:

Я не верю, что это связано с неявным И MongoDB, но с тем, как вы определяете фильтр. $gte Поле определено дважды, поэтому второе значение перезаписывает первое. Вот пример:

 x = { $gte: 0, $lte: 20, $gte: 10 }
console.log(x) 

Как вы можете видеть, второе значение для $gte -это то, которое остается.

Вместо этого мы можем взглянуть на то, какой диапазон значений на самом деле имеет значение, учитывая три переменные, floor , cursor , и ceiling .

Вы хотите найти сообщения , где floor <= likeCount <= ceiling и cursor <= likeCount .

Скажем cursor <= floor так . Поскольку cursor меньше или равно floor , вы можете гарантировать, что likeCount больше, чем cursor , между floor и ceiling с фильтром { likeCount: { $gte: floor, $lte: ceiling }} .

Если cursor > floor бы , то фильтр { likeCount: { $gte: cursor, $lte: ceiling }} сработал бы.

Имея это в виду, вы могли бы сделать что-то вроде этого:

 Post.find({
  likeCount: {
    $gte: cursor <= floor ? floor : cursor,
    $lte: ceiling,
  }
})
 

Комментарии:

1. На самом деле это могло бы непреднамеренно дать мне ответ. Неявное И с запятыми не работает, когда одно и то же выражение используется более одного раза. В документах они используют оператор $или в примере, здесь это $gte. Отчасти это то, на что вы указываете, и я просто этого не видел. 1 за то, что привел меня к правильному ответу.