Đây là "theo thiết kế" của $lookup
thực hiện. Thực ra là gì xảy ra "under the hood" là MongoDB internall chuyển đổi các đối số trong $lookup
sang biểu cảm mới định dạng bằng $expr
và $in
. Ngay cả trong các phiên bản trước khi biểu cảm này đã được triển khai, cơ chế nội bộ cho "mảng giá trị" thực sự rất giống nhau.
Giải pháp ở đây là duy trì một bản sao của mảng ban đầu làm tham chiếu để sắp xếp lại thứ tự "đã tham gia" mặt hàng:
collection.aggregate([
{"$match": {"_id": ObjectId("5c781752176c512f180048e3") }},
{"$lookup": {
"from": "collection2",
"let": { "classIds": "$Classes.ID" },
"pipeline": [
{ "$match": {
"$expr": { "$in": [ "$_id", "$$classIds" ] }
}},
{ "$addFields": {
"sort": {
"$indexOfArray": [ "$$classIds", "$_id" ]
}
}},
{ "$sort": { "sort": 1 } },
{ "$addFields": { "sort": "$$REMOVE" }}
],
"as": "results"
}}
])
Hoặc bằng $lookup
kế thừa cách sử dụng:
collection.aggregate([
{"$match": {"_id": ObjectId("5c781752176c512f180048e3") }},
{"$lookup": {
"from": "collection2",
"localField": "Classes.ID",
"foreignField": "_id",
"as": "results"
}},
{ "$unwind": "$results" },
{ "$addFields": {
"sort": {
"$indexOfArray": [ "$Classes.ID", "$results._id" ]
}
}},
{ "$sort": { "_id": 1, "sort": 1 } },
{ "$group": {
"_id": "$_id",
"Name": { "$first": "$Name" },
"Classes": { "$first": "$Classes" },
"results": { "$push": "$results" }
}}
])
Cả hai biến thể đều tạo ra cùng một đầu ra:
{
"_id" : ObjectId("5c781752176c512f180048e3"),
"Name" : "Pedro",
"Classes" : [
{
"ID" : ObjectId("5c7af2b2f6f6e47c9060d7ce")
},
{
"ID" : ObjectId("5c7af2bcf6f6e47c9060d7cf")
},
{
"ID" : ObjectId("5c7af2aaf6f6e47c9060d7cd")
}
],
"results" : [
{
"_id" : ObjectId("5c7af2b2f6f6e47c9060d7ce"),
"variable1" : "B"
},
{
"_id" : ObjectId("5c7af2bcf6f6e47c9060d7cf"),
"variable1" : "C"
},
{
"_id" : ObjectId("5c7af2aaf6f6e47c9060d7cd"),
"variable1" : "A"
}
]
}
Khái niệm chung là sử dụng $indexOfArray
so với _id
giá trị từ "đã tham gia" nội dung cần tìm là "chỉ mục" vị trí trong mảng nguồn ban đầu từ "$Classes.ID"
. $lookup
khác nhau các biến thể cú pháp có các cách tiếp cận khác nhau đối với cách bạn truy cập vào bản sao này và cách bạn xây dựng lại về cơ bản.
$sort
tất nhiên đặt thứ tự của các tài liệu thực tế, hoặc đang được bên trong xử lý đường ống cho biểu mẫu biểu cảm hoặc thông qua các tài liệu tiếp xúc của $unwind
. Nơi bạn đã sử dụng $unwind
sau đó bạn sẽ $group
trở lại biểu mẫu tài liệu ban đầu.
LƯU Ý :Các ví dụ sử dụng ở đây phụ thuộc vào MongoDB 3.4 cho
$indexOfArray
ít nhất và$$REMOVE
căn chỉnh với MongoDB 3.6 giống như biểu cảm$lookup
.Có các cách tiếp cận khác để sắp xếp lại mảng cho các bản phát hành trước, nhưng những cách này được thể hiện chi tiết hơn về thứ tự đảm bảo điều khoản $ in của MongoDB. Thực tế, mức tối thiểu mà bạn hiện có thể chạy dưới dạng phiên bản MongoDB sản xuất là bản phát hành 3.4.
Xem Chính sách hỗ trợ trong Máy chủ MongoDB để biết chi tiết đầy đủ về các bản phát hành được hỗ trợ và ngày kết thúc.