Tốt nhất có lẽ nên tìm kiếm bằng cách sử dụng $ where
ngoài truy vấn thông thường và vẫn giữ mọi thứ trên máy chủ:
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")
}
})
Và nếu bạn có MongoDB 3.4 có hỗ trợ $ indexOfArray
và $ range
, thì nó có thể trông dài hơn nhưng nó thực sự hiệu quả nhất với $ 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"
}
}}
])
Vì vậy, thực sự không có hoạt động truy vấn thực tế nào thực thi điều đó, nhưng cả hai trường hợp này đều giữ lựa chọn "trên máy chủ" thay vì gửi dữ liệu qua dây tới máy khách và sau đó lọc.
Bởi vì nếu bạn làm điều đó, nó sẽ phủ nhận mục đích của việc sử dụng cơ sở dữ liệu ngay từ đầu. Vì vậy, bạn thực sự muốn điều này xảy ra trên máy chủ.