Khung tổng hợp không "xử lý" các mảng theo cách giống như được áp dụng cho .find ()
truy vấn nói chung. Điều này không chỉ đúng với các thao tác như .sort ()
, mà còn với các toán tử khác, và cụ thể là $ slice
, mặc dù ví dụ đó sắp được sửa chữa (sẽ có thêm sau).
Vì vậy, hầu như không thể giải quyết bất cứ điều gì bằng cách sử dụng biểu mẫu "ký hiệu dấu chấm" với chỉ mục của một vị trí mảng như bạn có. Nhưng có một cách để giải quyết vấn đề này.
Những gì bạn "có thể" làm về cơ bản là tìm ra phần tử mảng "thứ n" thực sự là một giá trị gì và sau đó trả lại giá trị đó dưới dạng một trường có thể được sắp xếp:
db.test.aggregate([
{ "$unwind": "$items" },
{ "$group": {
"_id": "$_id",
"items": { "$push": "$items" },
"itemsCopy": { "$push": "$items" },
"first": { "$first": "$items" }
}},
{ "$unwind": "$itemsCopy" },
{ "$project": {
"items": 1,
"itemsCopy": 1,
"first": 1,
"seen": { "$eq": [ "$itemsCopy", "$first" ] }
}},
{ "$match": { "seen": false } },
{ "$group": {
"_id": "$_id",
"items": { "$first": "$items" },
"itemsCopy": { "$push": "$itemsCopy" },
"first": { "$first": "$first" },
"second": { "$first": "$itemsCopy" }
}},
{ "$sort": { "second": -1 } }
])
Đó là một cách tiếp cận khủng khiếp và "có thể lặp lại", trong đó bạn về cơ bản "từng bước qua" từng phần tử mảng bằng cách lấy $ đầu tiên
khớp với mỗi tài liệu từ mảng sau khi xử lý với $ thư giãn
. Sau đó, sau khi $ unwind
một lần nữa, bạn kiểm tra xem liệu các phần tử mảng đó có giống với (các) phần tử đã được "nhìn thấy" từ các vị trí mảng đã xác định hay không.
Điều đó thật tồi tệ, và càng tệ hơn khi bạn muốn di chuyển nhiều vị trí hơn, nhưng kết quả là:
{ "_id" : 2, "items" : [ 0, 3, 4 ], "itemsCopy" : [ 3, 4 ], "first" : 0, "second" : 3 }
{ "_id" : 1, "items" : [ 1, 2, 0 ], "itemsCopy" : [ 2, 0 ], "first" : 1, "second" : 2 }
{ "_id" : 3, "items" : [ 2, 1, 5 ], "itemsCopy" : [ 1, 5 ], "first" : 2, "second" : 1 }
May mắn thay, các bản phát hành sắp tới của MongoDB (như hiện có trong các bản phát hành thiết bị) có "bản sửa lỗi" cho điều này. Nó có thể không phải là bản sửa lỗi "hoàn hảo" mà bạn mong muốn, nhưng nó giải quyết được vấn đề cơ bản.
Có một $ slice
mới toán tử có sẵn cho khung tổng hợp ở đó và nó sẽ trả về (các) phần tử bắt buộc của mảng từ các vị trí được lập chỉ mục:
db.test.aggregate([
{ "$project": {
"items": 1,
"slice": { "$slice": [ "$items",1,1 ] }
}},
{ "$sort": { "slice": -1 } }
])
Sản xuất:
{ "_id" : 2, "items" : [ 0, 3, 4 ], "slice" : [ 3 ] }
{ "_id" : 1, "items" : [ 1, 2, 0 ], "slice" : [ 2 ] }
{ "_id" : 3, "items" : [ 2, 1, 5 ], "slice" : [ 1 ] }
Vì vậy, bạn có thể lưu ý rằng là một "lát cắt", kết quả vẫn là một "mảng", tuy nhiên $ sort
trong khung tổng hợp luôn sử dụng "vị trí đầu tiên" của mảng để sắp xếp nội dung. Điều đó có nghĩa là với một giá trị đơn lẻ được trích xuất từ vị trí được lập chỉ mục (giống như quy trình dài ở trên) thì kết quả sẽ được sắp xếp như bạn mong đợi.
Các trường hợp cuối cùng ở đây chỉ là cách nó hoạt động. Hoặc sống với loại hoạt động bạn cần từ phía trên để làm việc với vị trí được lập chỉ mục của mảng hoặc "đợi" cho đến khi một phiên bản sáng bóng hoàn toàn mới xuất hiện để giải cứu bạn với các toán tử tốt hơn.