#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 за то, что привел меня к правильному ответу.