การ Sort เอกสารตามความต่าง (Difference) ของค่าใน Array สามารถทำได้ด้วย Aggregation Pipeline โดยคำนวณความต่างใน Stage $project แล้ว $sort เนื้อหานี้สาธิตการหาความต่างระหว่าง Element ตำแหน่งสุดท้าย 2 ตัวใน Array Scores
ตัวอย่างข้อมูลทดสอบ
> 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") }
แสดงข้อมูลทั้งหมด
> db.demo155.find();
{
"_id" : ObjectId("5e354584fdf09dd6d08539e3"),
"Scores" : [ { "Value" : 45 }, { "Value" : 50 } ]
}
{
"_id" : ObjectId("5e35458efdf09dd6d08539e4"),
"Scores" : [ { "Value" : 60 }, { "Value" : 10 } ]
}
{
"_id" : ObjectId("5e354599fdf09dd6d08539e5"),
"Scores" : [ { "Value" : 100 }, { "Value" : 95 } ]
}
Aggregation Pipeline คำนวณและ Sort
> 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 } }
])
ผลลัพธ์ (เรียงจากความต่างมากไปน้อย)
{
"_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
}
คำอธิบาย Pipeline
$match: กรองเฉพาะ Doc ที่มี Scores.1 (มี Element อย่างน้อย 2 ตัว)$project: คำนวณsub= ค่าตัวสุดท้าย - ค่าตัวก่อนสุดท้าย$arrayElemAt: [ "$Scores", -2 ]= Element ตำแหน่ง -2 (ตัวก่อนสุดท้าย)$arrayElemAt: [ "$Scores", -1 ]= Element ตำแหน่ง -1 (ตัวสุดท้าย)$letกำหนดตัวแปร f, l แล้ว$subtractคำนวณ l.Value - f.Value
$sort: { sub: -1 }: เรียงจากค่ามากไปน้อย (Descending)