Nếu bạn muốn loại ràng buộc đó trong truy vấn, thì về cơ bản bạn có hai tùy chọn tùy thuộc vào những gì phiên bản MongoDB của bạn hỗ trợ:
MongoDB 3.6
Bạn nên sử dụng $ expr
"thêm vào" với bất kỳ điều kiện truy vấn thông thường nào để thực sự chọn tài liệu hợp lệ:
var A = 10, B = 40;
Model.find({
"subDocs.value": { "$all": [A, B] },
"$expr": {
"$lt": [
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", A ]}
]},
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", B ]}
]}
]
}
})
Hoặc khớp với "cuối cùng" sự xuất hiện:
Model.find({
"subDocs.value": { "$all": [A, B] },
"$expr": {
"$lt": [
{ "$arrayElemAt": [
"$subDocs.index",
{ "$subtract": [
{ "$subtract": [{ "$size": "$subDocs.value" }, 1 ] },
{ "$indexOfArray": [ { "$reverseArray": "$subDocs.value" }, A ] }
]}
]},
{ "$arrayElemAt": [
"$subDocs.index",
{ "$subtract": [
{ "$subtract": [{ "$size": "$subDocs.value" }, 1 ] },
{ "$indexOfArray": [ { "$reverseArray": "$subDocs.value" }, B ] }
]}
]}
]
}
})
Các phiên bản trước đó
Tương tự, nhưng không có toán tử gốc, bạn cần sử dụng đánh giá JavaScript của $ ở đâu
:
var A = 10, B = 40;
Model.find({
"subDocs.value": { "$all": [A, B] },
"$where": `this.subDocs.find( e => e.value === ${A}).index
< this.subDocs.find( e => e.value === ${B}).index`
})
Hoặc khớp với "cuối cùng" sự xuất hiện:
Model.find({
"subDocs.value": { "$all": [10,40] },
"$where": `let arr = this.subDocs.reverse();
return arr.find( e => e.value === ${A}).index
> arr.find( e => e.value === ${B}).index`
})
Nếu bạn cần điều đó trong quy trình tổng hợp, thì bạn sẽ sử dụng $ redact
và logic tương tự như ví dụ đầu tiên để thay thế:
var A = 10, B = 40;
Model.aggregate([
{ "$match": { "subDocs.value": { "$all": [A, B] } } },
{ "$redact": {
"$cond": {
"if": {
"$lt": [
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", A ]}
]},
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", B ]}
]}
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Chỉ cần nói rằng "logic so sánh" không thực sự có nguồn gốc từ chính "các biểu thức toán tử truy vấn", vì vậy, phần duy nhất mà "tối ưu" có thể được áp dụng cho một chỉ mục đang sử dụng $ all
toán tử truy vấn trong mọi trường hợp. Logic cơ bản còn lại thực sự áp dụng "sau khi" biểu thức chính được đánh giá và "bổ sung" để không có kết quả nào được trả về khác với những kết quả đáp ứng biểu thức với $expr
hoặc $ where
.
Logic cơ bản của mỗi loại về cơ bản là trích xuất giá trị của "index"
thuộc tính từ thành viên mảng "đầu tiên" thực sự khớp với giá trị tương ứng trong "value"
tài sản. Trường hợp giá trị này là "nhỏ hơn", thì điều kiện là true
và điều này thỏa mãn tài liệu đang được trả lại.
Vì vậy, lưu ý rằng "đánh giá được tính toán" phù hợp với hiệu quả của toán tử truy vấn và không được sử dụng "kết hợp" với các điều kiện toán tử truy vấn khác có thể truy cập "chỉ mục", thì "quét toàn bộ bộ sưu tập" sẽ được bắt đầu.
Nhưng kết quả tổng thể chắc chắn hiệu quả hơn việc trả lại tất cả các mục phù hợp với điều kiện truy vấn đầu tiên và sau đó từ chối chúng trên con trỏ "sau khi" quay trở lại từ cơ sở dữ liệu.
Xem thêm tài liệu về $ arrayElemAt
, $ indexOfArray
, $ lt
và Array.find ()
cho JavaScript