Общий случай здесь заключается в том, что вы, вероятно, «должны» сгенерировать «диапазон», который находится между ними, и затем проверить, что массив НЕ содержит ни одного из этих возможных чисел:
var start = 3,
end = 6;
var range = Array(end - start + 1).fill(1).map(e => start++);
db.scores.find({
"score": {
"$elemMatch": { "$gte": start, "$lte": end },
"$not": {
"$elemMatch": { "$nin": range }
}
}
})
Вернет:
{ "_id" : 3, "score" : [ 5, 5 ] }
Поскольку это единственный элемент, который содержит что-то, попадающее в этот диапазон «только».
ЕСЛИ у вас есть ограничение, когда элементы имеют слишком много возможных значений для перечисления всего«диапазон», то вы либо используете $not
для «условия диапазона»:
db.scores.find({
"score": {
"$elemMatch": { "$gte": 3, "$lte": 6 },
"$not": {
"$elemMatch": {
"$not": { "$gte": 3, "$lte": 6 }
}
}
}
})
Или поочередно обрабатываете с дополнительным вычисленным условием,
Либоиспользуя $expr
:
db.scores.find({
"score": { "$elemMatch": { "$gte": 3, "$lte": 6 } },
"$expr": {
"$allElementsTrue": {
"$map": {
"input": "$score",
"in": {
"$and": [
{ "$gte": [ "$$this", 3 ] },
{ "$lte": [ "$$this", 6 ] }
]
}
}
}
}
})
или $redact
до MongoDB 3.6
db.scores.aggregate([
{ "$match": { "score": { "$elemMatch": { "$gte": 3, "$lte": 6 } } } },
{ "$redact": {
"$cond": {
"if": {
"$allElementsTrue": {
"$map": {
"input": "$score",
"in": {
"$and": [
{ "$gte": [ "$$this", 3 ] },
{ "$lte": [ "$$this", 6 ] }
]
}
}
}
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
или даже $where
с использованием условия JavaScript для сопоставления, когда ваша MongoDB не поддерживает ничего из перечисленного:
db.scores.find({
"score": { "$elemMatch": { "$gte": 3, "$lte": 6 } },
"$where": function() {
return this.score.every(e => e >= 3 && e <= 6)
}
})
Во всех случаях вы действительно хотите, чтобы это "положительное" условие для $elemMatch
, чтобы найти эти элементы "в пределах диапазона"архивирование индекса в этом поле .Ни один из других методов либо с использованием $not
и $nin
, либо с помощью условия агрегации $allElementsTrue
или Array.every()
может реально посмотреть на «индекс», чтобы выполнить условие.Они просто используются во всех случаях как «дополнительный фильтр», из которого можно «исключить» любые «потенциальные» совпадающие документы через «диапазон» из возможных результатов.