MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Filter hasil menurut Nilai Bidang Entri Array Terakhir

Jarak tempuh dapat bervariasi dalam hal ini dan mungkin ternyata "saat ini" proses yang Anda ikuti setidaknya "paling cocok". Tapi kita mungkin bisa melakukannya dengan lebih efisien.

Apa yang dapat Anda lakukan sekarang

Asalkan array Anda sudah "diurutkan" melalui menggunakan $sort pengubah dengan $push , maka Anda mungkin dapat melakukan ini:

db.somedb.find(
  { 
    "partn.is_partner": true,
    "$where": function() {
      return this.partn.slice(-1)[0].is_partner == true;
    }
  },
  { "partn": { "$slice": -1 } }
)

Jadi selama partn,is_partner adalah "diindeks" ini masih cukup efisien karena kondisi kueri awal itu dapat dipenuhi menggunakan indeks. Bagian yang tidak bisa adalah $where klausa di sini yang menggunakan evaluasi JavaScript.

Tapi apa bagian kedua di $where lakukan hanyalah "mengiris" elemen terakhir dari array dan menguji nilainya dari is_partner properti untuk melihat apakah itu benar. Hanya jika kondisi itu juga terpenuhi, dokumen dikembalikan.

Ada juga $slice operator proyeksi. Ini melakukan hal yang sama dalam mengembalikan elemen terakhir dari array. Pencocokan palsu sudah difilter, jadi ini hanya menampilkan elemen terakhir yang benar.

Dikombinasikan dengan indeks seperti yang disebutkan, maka ini akan cukup cepat mengingat dokumen telah dipilih dan kondisi JavaScript hanya memfilter sisanya. Perhatikan bahwa tanpa bidang lain dengan kondisi kueri standar yang cocok, sebuah $where klausa tidak dapat menggunakan indeks. Jadi, selalu coba gunakan "hemat" dengan kondisi kueri lainnya.

Apa yang dapat Anda lakukan di masa depan

Selanjutnya, meskipun tidak tersedia pada saat penulisan, tetapi pasti dalam waktu dekat akan menjadi $slice operator untuk kerangka agregasi. Ini saat ini di cabang pengembangan, tetapi di sini adalah cara kerjanya:

db.somedb.aggregate([
  { "$match": { "partn.is_partner": true } },
  { "$redact": {
    "$cond": {
      "if": { 
        "$anyElementTrue": {
          "$map": {
            "input": { "$slice": ["$partn",-1] },
            "as": "el",
            "in": "$$el.is_partner"
          }
        }
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }},
  { "$project": {
      "partn": { "$slice": [ "$partn",-1 ] }
  }}
])

Menggabungkan $slice dalam $redact tahap disini memungkinkan dokumen difilter dengan kondisi logis, pengujian dokumen. Dalam hal ini $slice menghasilkan larik elemen tunggal yang dikirim ke $map untuk hanya mengekstrak is_partner tunggal nilai ( masih sebagai array ). Karena ini masih merupakan larik elemen tunggal, tes lainnya adalah $anyElementTrue yang menjadikan ini hasil boolean tunggal, cocok untuk $cond .

$redact di sini memutuskan hasil tersebut apakah akan $$KEEP atau $$PRUNE dokumen dari hasil. Nanti kita gunakan $slice lagi dalam proyek untuk hanya mengembalikan elemen terakhir dari array setelah pemfilteran.

Itu bekerja persis seperti yang dilakukan versi JavaScript, dengan pengecualian bahwa ini menggunakan semua operator berkode asli, dan karenanya harus sedikit lebih cepat daripada alternatif JavaScript.

Kedua formulir mengembalikan dokumen pertama Anda seperti yang diharapkan:

{
    "_id" : 0,
    "partn" : [
            {
                    "date" : ISODate("2015-07-28T00:59:14.963Z"),
                    "is_partner" : true
            },
            {
                    "date" : ISODate("2015-07-28T01:00:32.771Z"),
                    "is_partner" : false
            },
            {
                    "date" : ISODate("2015-07-28T01:15:29.916Z"),
                    "is_partner" : true
            },
            {
                    "date" : ISODate("2015-08-05T13:48:07.035Z"),
                    "is_partner" : false
            },
            {
                    "date" : ISODate("2015-08-05T13:50:56.482Z"),
                    "is_partner" : true
            }
    ]
}

Tangkapan besar di sini dengan keduanya adalah array Anda harus sudah diurutkan sehingga tanggal terbaru adalah yang pertama. Tanpa itu, maka Anda memerlukan kerangka kerja agregasi untuk $sort array, seperti yang Anda lakukan sekarang.

Tidak terlalu efisien, jadi itu sebabnya Anda harus "menyortir" array Anda dan mempertahankan urutannya pada setiap pembaruan.

Sebagai trik praktis, ini sebenarnya akan mengurutkan ulang semua elemen array di semua dokumen koleksi dalam satu pernyataan sederhana:

db.somedb.update(
    {},
    { "$push": { 
        "partn": { "$each": [], "$sort": { "date": 1 } }
    }},
    { "multi": true }
)

Jadi, bahkan jika Anda tidak "mendorong" elemen baru ke dalam array dan hanya memperbarui properti, Anda selalu dapat menerapkan konstruksi dasar itu untuk menjaga agar array tetap teratur seperti yang Anda inginkan.

Layak dipertimbangkan karena seharusnya membuat segalanya lebih cepat.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Bagaimana cara menghubungkan PHP dengan MongoDB?

  2. Cara mudah untuk Menyinkronkan Data antara MongoDB dan Apache Solr

  3. MongoDB $isoWeekYear

  4. Gandakan koleksi mongodb

  5. cara menanyakan data di dalam array koleksi menggunakan luwak