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

Cara menggunakan $regex di dalam $or sebagai Ekspresi Agregasi

Semua yang ada di dalam $expr adalah ekspresi agregasi, dan dokumentasi tidak boleh "mengatakan Anda tidak bisa secara eksplisit" , tetapi kurangnya nama operator dan Masalah JIRA SERVER-11947 pasti mengatakan itu. Jadi jika Anda membutuhkan ekspresi reguler maka Anda benar-benar tidak memiliki pilihan lain selain menggunakan $where sebagai gantinya:

db.getCollection('permits').find({
  "$where": function() {
    var description = this.inspections
       .sort((a,b) => b.inspectionDate.valueOf() - a.inspectionDate.valueOf())
       .shift().description;

     return /^Found a .* at the property$/.test(description) ||
           description === "Health Inspection";

  }
})

Anda masih dapat menggunakan $expr dan ekspresi agregasi untuk pencocokan persis, atau simpan saja perbandingan dalam $where omong-omong. Tetapi saat ini satu-satunya ekspresi reguler yang dipahami MongoDB adalah $regex dalam ekspresi "query" .

Jika Anda benar-benar "memerlukan" ekspresi pipeline agregasi yang menghalangi Anda menggunakan $where , maka satu-satunya pendekatan yang valid saat ini adalah pertama-tama "memproyeksikan" bidang secara terpisah dari larik dan kemudian $match dengan ekspresi kueri reguler:

db.getCollection('permits').aggregate([
  { "$addFields": {
     "lastDescription": {
       "$arrayElemAt": [
         "$inspections.description",
         { "$indexOfArray": [
           "$inspections.inspectionDate",
           { "$max": "$inspections.inspectionDate" }
         ]}
       ]
     }
  }},
  { "$match": {
    "lastDescription": {
      "$in": [/^Found a .* at the property$/,/Health Inspection/]
    }
  }}
])

Yang membawa kami pada fakta bahwa Anda tampaknya mencari item dalam array dengan nilai tanggal maksimum. Sintaks JavaScript harus memperjelas bahwa pendekatan yang benar di sini adalah $sort array pada "perbarui". Dengan cara itu item "pertama" dalam array bisa menjadi "terbaru". Dan ini adalah sesuatu yang dapat Anda lakukan dengan kueri biasa.

Untuk mempertahankan urutan, pastikan item baru ditambahkan ke larik dengan $push dan $sort seperti ini:

db.getCollection('permits').updateOne(
  { "_id": _idOfDocument },
  {
    "$push": {
      "inspections": {
        "$each": [{ /* Detail of inspection object */ }],
        "$sort": { "inspectionDate": -1 }
      }
    }
  }
)

Bahkan dengan argumen array kosong ke $each sebuah updateMany() akan memperbarui semua dokumen Anda yang ada:

db.getCollection('permits').updateMany(
  { },
  {
    "$push": {
      "inspections": {
        "$each": [],
        "$sort": { "inspectionDate": -1 }
      }
    }
  }
)

Ini benar-benar hanya diperlukan ketika Anda sebenarnya "mengubah" tanggal yang disimpan selama pembaruan, dan pembaruan tersebut paling baik dikeluarkan dengan bulkWrite() untuk melakukan "baik" pembaruan dan "sort" array secara efektif:

db.getCollection('permits').bulkWrite([
  { "updateOne": {
    "filter": { "_id": _idOfDocument, "inspections._id": indentifierForArrayElement },
    "update": {
      "$set": { "inspections.$.inspectionDate": new Date() }
    }
  }},
  { "updateOne": {
    "filter": { "_id": _idOfDocument },
    "update": {
      "$push": { "inspections": { "$each": [], "$sort": { "inspectionDate": -1 } } }
    }
  }}
])

Namun jika Anda tidak pernah benar-benar "mengubah" tanggal, maka mungkin lebih masuk akal untuk menggunakan $position pengubah dan "pra-pend" ke array alih-alih "menambahkan", dan menghindari overhead $sort :

db.getCollection('permits').updateOne(
  { "_id": _idOfDocument },
  { 
    "$push": { 
      "inspections": {
        "$each": [{ /* Detail of inspection object */ }],
        "$position": 0
      }
    }
  }
)

Dengan array yang diurutkan secara permanen atau setidaknya dibuat sehingga tanggal "terbaru" sebenarnya selalu merupakan entri "pertama", maka Anda cukup menggunakan ekspresi kueri reguler:

db.getCollection('permits').find({
  "inspections.0.description": { 
    "$in": [/^Found a .* at the property$/,/Health Inspection/]
  }
})

Jadi pelajarannya di sini adalah jangan mencoba dan memaksakan ekspresi yang dihitung pada logika Anda di mana Anda benar-benar tidak perlu melakukannya. Seharusnya tidak ada alasan kuat mengapa Anda tidak dapat mengurutkan konten larik sebagai "disimpan" untuk memiliki "tanggal terbaru pertama " , dan bahkan jika Anda merasa membutuhkan array dalam urutan lain, Anda mungkin harus mempertimbangkan kasus penggunaan mana yang lebih penting.

Setelah diurutkan ulang, Anda bahkan dapat memanfaatkan indeks sampai batas tertentu selama ekspresi reguler ditambatkan ke awal string atau setidaknya sesuatu yang lain dalam ekspresi kueri melakukan pencocokan persis.

Jika Anda merasa benar-benar tidak dapat menyusun ulang array, maka $where kueri adalah satu-satunya pilihan Anda saat ini hingga masalah JIRA teratasi. Yang mudah-mudahan sebenarnya untuk rilis 4.1 seperti yang ditargetkan saat ini, tapi itu lebih dari kemungkinan 6 bulan hingga satu tahun pada perkiraan terbaik.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Cara mengatur mongod.conf bind_ip dengan beberapa alamat ip

  2. MongoDB :Bagaimana cara mengalikan bidang yang hanya muncul di $project?

  3. Memasang di Mongo DB menggunakan driver C # resmi

  4. MongoDB :temukan nilai dalam Array dengan banyak kriteria

  5. Agregasi MongoDB pada rentang