Sử dụng aggregation pipeline để tính hiệu giữa hai phần tử mảng (ví dụ phần tử cuối và phần tử trước cuối) và sắp xếp theo kết quả đó.
Dữ liệu mẫu
> db.demo155.insertOne({"Scores":[{"Value":45},{"Value":50}]});
{ "acknowledged" : true, "insertedId" : ObjectId("5e354584fdf09dd6d08539e3") }
> db.demo155.insertOne({"Scores":[{"Value":60},{"Value":10}]});
{ "acknowledged" : true, "insertedId" : ObjectId("5e35458efdf09dd6d08539e4") }
> db.demo155.insertOne({"Scores":[{"Value":100},{"Value":95}]});
{ "acknowledged" : true, "insertedId" : ObjectId("5e354599fdf09dd6d08539e5") }
Pipeline aggregate
> db.demo155.aggregate([
... { "$match": { "Scores.1": { "$exists": true } } },
... { "$project": {
... "Scores": "$Scores",
... "sub": {
... "$let": {
... "vars": {
... "f": { "$arrayElemAt": [ "$Scores", -2 ] },
... "l": { "$arrayElemAt": [ "$Scores", -1 ] }
... },
... "in": { "$subtract": [ "$$l.Value", "$$f.Value" ] }
... }
... }
... }},
... { "$sort": { "sub": -1 } }
... ])
Kết quả
{ "_id" : ObjectId("5e354584fdf09dd6d08539e3"), "Scores" : [ { "Value" : 45 }, { "Value" : 50 } ], "sub" : 5 }
{ "_id" : ObjectId("5e354599fdf09dd6d08539e5"), "Scores" : [ { "Value" : 100 }, { "Value" : 95 } ], "sub" : -5 }
{ "_id" : ObjectId("5e35458efdf09dd6d08539e4"), "Scores" : [ { "Value" : 60 }, { "Value" : 10 } ], "sub" : -50 }
Giải thích pipeline:
$match: Chỉ giữ tài liệu có ít nhất 2 phần tử trongScores(kiểm traScores.1tồn tại).$project: Tạo trườngsubbằng cách lấy phần tử -2 (phần tử trước cuối) và -1 (phần tử cuối) qua$arrayElemAt, rồi trừValuecủa chúng.$sort: Sắp xếp giảm dần theosub.
Cải tiến MongoDB 5.0+: Có thể dùng $getField hoặc $reduce để code ngắn gọn hơn.