Mongodb: จัดเรียงตามนิพจน์ที่กำหนดเอง

จะจัดเรียงผลลัพธ์ตามนิพจน์ที่กำหนดเองซึ่งฉันใช้ใน find ได้อย่างไร

คอลเลกชันประกอบด้วยเอกสารที่มีคุณสมบัติดังต่อไปนี้ เช่น:

{
    "_id" : ObjectId("5ef1cd704b35c6d6698f2050"),
    "Name" : "TD",
    "Date" : ISODate("2021-06-23T09:37:51.976Z"),
    "A" : "19.36",
    "B" : 2.04,
}

ฉันใช้แบบสอบถาม find ต่อไปนี้เพื่อรับบันทึกที่มี Date ตั้งแต่ปี 2022-01-01 และอัตราส่วนระหว่าง A ถึง B ต่ำกว่า 0.1:

db.getCollection('my_collection').find(
    {
            "experationDate" : 
            {
                    $gte: new ISODate("2022-01-01 00:00:00.000Z")
            },
            "$expr": 
            {
                "$lte": [ 
                            { "$divide": ["$A", "$B"] },
                            0.1
                        ] 
            }
            
    })

ตอนนี้ ฉันไม่สามารถหาวิธีที่เหมาะสมในการจัดเรียงผลลัพธ์ตามอัตราส่วนนี้ได้


person Gal Dreiman    schedule 24.11.2020    source แหล่งที่มา
comment
คุณสามารถใช้แบบสอบถามแบบรวมเพื่อทำงานเหล่านี้ทั้งหมดได้ ขั้นตอน $addFields สามารถใช้เพื่อคำนวณค่าที่ได้รับ และ $sort จะช่วยให้คุณสามารถเรียงลำดับค่าที่คำนวณได้   -  person prasad_    schedule 24.11.2020


คำตอบ (1)


คุณสามารถใช้ aggregate ด้วยวิธีนี้:

ค้นหาเอกสารที่คุณต้องการโดยใช้ $match เพิ่มฟิลด์ชื่อ ratio และใช้ในการจัดเรียง และสุดท้าย ไม่แสดงฟิลด์โดยใช้ $project:

db.collection.aggregate([
  { "$match": {
      "Date": { "$gte": ISODate("2020-01-01") },
      "$expr": { "$lte": [ { "$divide": [ "$B", { "$toDouble": "$A" } ] }, 0.1 ] } }
  },
  {
    "$set": {
      "ratio": { "$divide": [ "$B", { "$toDouble": "$A" } ] }
    }
  },
  {
    "$sort": { "ratio": 1 }
  },
  {
    "$project": { "ratio": 0 }
  }
])

ตัวอย่างที่นี่

อย่างไรก็ตาม ฉันได้ใช้ค่าอื่นเพื่อให้ได้ผลลัพธ์ อัตราส่วนระหว่าง 2.04 ถึง 19.36 มากกว่า 0.1 คุณแบ่ง A/B แล้ว แต่ฉันคิดว่าคุณหมายถึง B/A

อย่างไรก็ตาม สิ่งนี้ไม่สำคัญ คุณสามารถเปลี่ยนค่าได้ แต่แบบสอบถามจะยังคงใช้งานได้

นอกจากนี้บางทีนี่อาจทำงานได้ดีขึ้น เป็นแบบสอบถามเดียวกัน แต่อาจมีประสิทธิภาพมากกว่า (บางทีฉันไม่รู้) เพราะป้องกันการแบ่งแต่ละค่าออกเป็นคอลเลกชันสองครั้ง:

ขั้นแรกกรองตามวันที่ จากนั้นเพิ่มฟิลด์ ratio ให้กับแต่ละเอกสารที่พบ (และด้วยวิธีนี้ ไม่จำเป็นต้องแบ่งทุกเอกสาร) ตัวกรองอื่นที่ใช้อัตราส่วน การเรียงลำดับ และไม่ส่งออกฟิลด์

db.collection.aggregate([
  {
    "$match": { "Date": { "$gte": ISODate("2020-01-01") } }
  },
  {
    "$set": { "ratio": { "$divide": [ "$B", { "$toDouble": "$A" } ] } }
  },
  {
    "$match": { "ratio": { "$lte": 0.1 } }
  },
  {
    "$sort": { "ratio": 1 }
  },
  {
    "$project": { "ratio": 0 }
  }
])

ตัวอย่าง

person J.F.    schedule 24.11.2020
comment
เหตุใดคุณจึงต้องใช้ $project ที่นี่ - person Gal Dreiman; 24.11.2020
comment
ฉันได้เพิ่มฟิลด์ใหม่ ratio และฉันคิดว่าคุณไม่ต้องการส่งออกฟิลด์ - person J.F.; 24.11.2020
comment
เข้าใจแล้ว ขอบคุณ - person Gal Dreiman; 24.11.2020
comment
ยินดี! นอกจากนี้ ฉันได้อัปเดตแบบสอบถามเพื่อไม่ให้แบ่งสองครั้ง มีเพียงส่วนเดียวเท่านั้นและสำหรับเอกสารที่ date ตรงกันเท่านั้น - person J.F.; 24.11.2020