Mileage có thể khác nhau về điều này và nó cũng có thể hóa ra rằng "hiện tại" quá trình bạn đang theo dõi hoạt động ít nhất là "phù hợp nhất". Nhưng chúng tôi có thể làm hiệu quả hơn.
Bạn có thể làm gì bây giờ
Với điều kiện các mảng của bạn đã được "sắp xếp" qua sử dụng mã <> $ sort
bổ trợ bằng $ push
, thì bạn có thể làm được điều này:
db.somedb.find(
{
"partn.is_partner": true,
"$where": function() {
return this.partn.slice(-1)[0].is_partner == true;
}
},
{ "partn": { "$slice": -1 } }
)
Vì vậy, miễn là partn, is_partner
được "lập chỉ mục", điều này vẫn khá hiệu quả vì điều kiện truy vấn ban đầu có thể được đáp ứng bằng chỉ mục. Phần không thể là $ where
ở đây sử dụng đánh giá JavaScript.
Nhưng phần thứ hai đó là gì trong $ where
đang làm chỉ đơn giản là "cắt" phần tử cuối cùng khỏi mảng và kiểm tra giá trị của is_partner
tài sản để xem nếu nó là sự thật. Chỉ khi điều kiện đó cũng được đáp ứng thì tài liệu mới được trả về.
Ngoài ra còn có $ slice
toán tử chiếu. Điều này thực hiện tương tự khi trả về phần tử cuối cùng từ mảng. Các kết quả phù hợp sai đã được lọc, vì vậy phần tử này chỉ hiển thị phần tử cuối cùng đúng.
Kết hợp với chỉ mục như đã đề cập, thì điều này sẽ khá nhanh chóng vì các tài liệu đã được chọn sẵn và điều kiện JavaScript chỉ lọc phần còn lại. Lưu ý rằng không có trường khác có điều kiện truy vấn chuẩn để phù hợp, $ where
mệnh đề không thể sử dụng một chỉ mục. Vì vậy, hãy luôn cố gắng sử dụng "hạn chế" với các điều kiện truy vấn khác tại chỗ.
Bạn có thể làm gì trong tương lai
Tiếp theo, mặc dù không có sẵn tại thời điểm viết bài, nhưng chắc chắn trong tương lai gần sẽ là $ slice
toán tử cho khung tổng hợp. Đây hiện là nhánh của thiết bị đào, nhưng đây là một cái nhìn sơ lược về cách hoạt động của nó:
db.somedb.aggregate([
{ "$match": { "partn.is_partner": true } },
{ "$redact": {
"$cond": {
"if": {
"$anyElementTrue": {
"$map": {
"input": { "$slice": ["$partn",-1] },
"as": "el",
"in": "$$el.is_partner"
}
}
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": {
"partn": { "$slice": [ "$partn",-1 ] }
}}
])
Kết hợp $ slice
đó trong $ redact
ở đây thông báo cho các tài liệu được lọc với một điều kiện logic, kiểm tra tài liệu. Trong trường hợp này, $ slice
tạo ra một mảng phần tử duy nhất được gửi tới $ bản đồ
để chỉ trích xuất một is_partner
giá trị (vẫn là một mảng). Vì đây vẫn là một mảng phần tử đơn lẻ, nên thử nghiệm còn lại là $ anyElementTrue
điều này làm cho kết quả này là một kết quả boolean số ít, phù hợp với $ cond
.
$ redact
ở đây quyết định kết quả đó có nên $$ KEEP
hay không hoặc $$ PRUNE
tài liệu từ các kết quả. Sau đó, chúng tôi sử dụng $ slice
lại trong dự án để chỉ trả về phần tử cuối cùng của mảng sau khi lọc.
Điều đó hoạt động khá chính xác so với những gì phiên bản JavaScript làm, ngoại trừ việc phiên bản này sử dụng tất cả các toán tử được mã hóa gốc và do đó sẽ nhanh hơn một chút so với phiên bản JavaScript thay thế.
Cả hai biểu mẫu đều trả về tài liệu đầu tiên của bạn như mong đợi:
{
"_id" : 0,
"partn" : [
{
"date" : ISODate("2015-07-28T00:59:14.963Z"),
"is_partner" : true
},
{
"date" : ISODate("2015-07-28T01:00:32.771Z"),
"is_partner" : false
},
{
"date" : ISODate("2015-07-28T01:15:29.916Z"),
"is_partner" : true
},
{
"date" : ISODate("2015-08-05T13:48:07.035Z"),
"is_partner" : false
},
{
"date" : ISODate("2015-08-05T13:50:56.482Z"),
"is_partner" : true
}
]
}
Lợi ích lớn ở đây với cả hai là mảng của bạn phải được sắp xếp nên ngày mới nhất là ngày đầu tiên. Nếu không có điều đó, thì bạn cần khung tổng hợp để $ sort
mảng, giống như bạn đang làm bây giờ.
Không thực sự hiệu quả, vì vậy đó là lý do tại sao bạn nên "sắp xếp trước" mảng của mình và duy trì thứ tự trên mỗi lần cập nhật.
Là một thủ thuật hữu ích, điều này thực sự sẽ sắp xếp lại thứ tự tất cả các phần tử mảng trong tất cả các tài liệu bộ sưu tập trong một câu lệnh đơn giản:
db.somedb.update(
{},
{ "$push": {
"partn": { "$each": [], "$sort": { "date": 1 } }
}},
{ "multi": true }
)
Vì vậy, ngay cả khi bạn không "đẩy" một phần tử mới vào một mảng và chỉ cập nhật một thuộc tính, bạn luôn có thể áp dụng cấu trúc cơ bản đó để giữ cho mảng được sắp xếp theo cách bạn muốn.
Đáng xem xét vì nó sẽ giúp mọi thứ nhanh hơn nhiều.