Het beste is om te zoeken met $where
naast de normale zoekopdracht, en bewaar dingen nog steeds op de server:
db.getCollection('collection').find({
"array": {
"$elemMatch": { "field": "BCD", "enabled": "true" },
},
"$where": function() {
return this.array.map((e,i) => Object.assign(e,{ i }))
.filter( e => e.field === "BCD" && e.enabled === "true" )
.map( e => e.i )[0] <=
this.array.map(e => e.enabled).indexOf("true")
}
})
En als je MongoDB 3.4 hebt met ondersteuning voor $indexOfArray
en $range
, dan lijkt het misschien langer, maar het is eigenlijk het meest efficiënt met $redact
:
db.getCollection('collection').aggregate([
{ "$match": {
"array": {
"$elemMatch": { "field": "BCD", "enabled": "true" },
}
}},
{ "$redact": {
"$cond": {
"if": {
"$lte": [
{ "$arrayElemAt": [
{ "$map": {
"input": {
"$filter": {
"input": {
"$map": {
"input": {
"$zip": {
"inputs": [
"$array",
{ "$range": [0, { "$size": "$array" }] }
]
}
},
"as": "a",
"in": {
"field": { "$arrayElemAt": [ "$$a.field", 0 ] },
"enabled": { "$arrayElemAt": [ "$$a.enabled", 0 ] },
"index": { "$arrayElemAt": [ "$$a", 1 ] }
}
}
},
"as": "a",
"cond": {
"$and": [
{ "$eq": [ "$$a.field", "BCD" ] },
{ "$eq": [ "$$a.enabled", "true" ] }
]
}
}
},
"as": "a",
"in": "$$a.index"
}},
0
]},
{ "$indexOfArray": [ "$array.enabled", "true" ] }
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Er is dus geen echte query-operatie die dat afdwingt, maar in beide gevallen blijft de selectie "op de server" staan in plaats van gegevens over de kabel naar de client te sturen en vervolgens te filteren.
Want als je dat doet, ontken je het doel van het gebruik van een database in de eerste plaats. Dus je wilt echt dat dit op de server gebeurt.