Mongodb: Urutkan berdasarkan ekspresi khusus

Bagaimana cara mengurutkan hasil berdasarkan ekspresi khusus yang saya gunakan di find?

Koleksinya berisi dokumen dengan atribut berikut misalnya:

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

Saya menggunakan kueri find berikut untuk mendapatkan catatan dengan Date sejak 01-01-2022 dan rasio antara A dan B lebih rendah dari 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
                        ] 
            }
            
    })

Sekarang, saya tidak dapat menemukan cara yang tepat untuk mengurutkan hasil berdasarkan rasio ini.


person Gal Dreiman    schedule 24.11.2020    source sumber
comment
Anda dapat menggunakan kueri agregasi untuk melakukan semua tugas ini. Tahap $addFields dapat digunakan untuk menghitung nilai turunan dan $sort akan memungkinkan Anda mengurutkan berdasarkan nilai yang dihitung.   -  person prasad_    schedule 24.11.2020


Jawaban (1)


Anda dapat menggunakan aggregate dengan cara ini:

Cari dokumen yang ingin Anda gunakan $match, tambahkan bidang bernama ratio dan gunakan untuk mengurutkan. Dan terakhir, bidang tersebut tidak ditampilkan menggunakan $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 }
  }
])

Contoh di sini

Ngomong-ngomong, saya telah menggunakan nilai lain untuk mendapatkan hasil. Rasio antara 2,04 dan 19,36 lebih besar dari 0,1. Anda telah membagi A/B tetapi menurut saya yang Anda maksud adalah B/A.

Omong-omong, ini tidak penting, Anda dapat mengubah nilai tetapi kueri akan tetap berfungsi dengan baik.

Juga, mungkin ini bisa bekerja lebih baik. Adalah kueri yang sama, tetapi bisa lebih efisien (mungkin, saya tidak tahu) karena mencegah membagi setiap nilai ke dalam koleksi dua kali:

Filter terlebih dahulu berdasarkan tanggal, lalu tambahkan kolom ratio ke setiap dokumen yang ditemukan (dan dengan cara ini tidak perlu membagi setiap dokumen). Filter lain menggunakan rasio, pengurutan, dan bukan keluaran bidang.

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 }
  }
])

Contoh

person J.F.    schedule 24.11.2020
comment
Mengapa Anda perlu menggunakan $project di sini? - person Gal Dreiman; 24.11.2020
comment
Saya telah menambahkan bidang baru ratio dan saya berasumsi Anda tidak ingin menampilkan bidang tersebut. - person J.F.; 24.11.2020
comment
Mengerti, Terima kasih. - person Gal Dreiman; 24.11.2020
comment
Terima kasih kembali! Selain itu, saya telah memperbarui kueri agar tidak membagi dua kali. Pembagiannya hanya satu dan hanya untuk dokumen yang datenya sudah cocok. - person J.F.; 24.11.2020