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

Menemukan dua elemen dalam larik dokumen yang muncul dalam urutan tertentu

Jika Anda menginginkan batasan semacam itu dalam kueri, maka pada dasarnya Anda memiliki dua opsi tergantung pada apa yang didukung oleh versi MongoDB Anda:

MongoDB 3.6

Anda sebaiknya menggunakan $expr "selain itu" ke kondisi kueri normal apa pun untuk benar-benar memilih dokumen yang valid:

var A = 10, B = 40;

Model.find({
  "subDocs.value": { "$all": [A, B] },
  "$expr": {
    "$lt": [
      { "$arrayElemAt": [
        "$subDocs.index",
        { "$indexOfArray": [ "$subDocs.value", A ]}
      ]},
      { "$arrayElemAt": [
        "$subDocs.index",
        { "$indexOfArray": [ "$subDocs.value", B ]}  
      ]}
    ]
  }
})

Atau mencocokkan "terakhir" kejadian:

Model.find({
  "subDocs.value": { "$all": [A, B] },
  "$expr": {
    "$lt": [
      { "$arrayElemAt": [
        "$subDocs.index",
        { "$subtract": [
          { "$subtract": [{ "$size": "$subDocs.value" }, 1 ] },
          { "$indexOfArray": [ { "$reverseArray": "$subDocs.value" }, A ] }
        ]}
      ]},
      { "$arrayElemAt": [
        "$subDocs.index",
        { "$subtract": [
          { "$subtract": [{ "$size": "$subDocs.value" }, 1 ] },
          { "$indexOfArray": [ { "$reverseArray": "$subDocs.value" }, B ] }
        ]}
      ]}
    ]
  }
})

Versi Sebelumnya

Hal yang sama, tetapi tanpa operator asli Anda perlu menggunakan evaluasi JavaScript $where :

var A = 10, B = 40;

Model.find({
  "subDocs.value": { "$all": [A, B] },
  "$where": `this.subDocs.find( e => e.value === ${A}).index
      < this.subDocs.find( e => e.value === ${B}).index`
})

Atau mencocokkan "terakhir" kejadian:

Model.find({
  "subDocs.value": { "$all": [10,40] },
  "$where": `let arr = this.subDocs.reverse();
      return arr.find( e => e.value === ${A}).index
        > arr.find( e => e.value === ${B}).index`
})

Jika Anda membutuhkannya dalam pipeline agregasi, Anda akan menggunakan $redact dan logika yang mirip dengan contoh pertama sebagai gantinya:

var A = 10, B = 40;

Model.aggregate([
  { "$match": { "subDocs.value": { "$all": [A, B] } } },
  { "$redact": {
    "$cond": {
      "if": {
        "$lt": [
          { "$arrayElemAt": [
            "$subDocs.index",
            { "$indexOfArray": [ "$subDocs.value", A ]}
          ]},
          { "$arrayElemAt": [
            "$subDocs.index",
            { "$indexOfArray": [ "$subDocs.value", B ]}  
          ]}
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

Cukuplah untuk mengatakan bahwa "logika perbandingan" sebenarnya bukan asli dari "ekspresi operator kueri" itu sendiri, jadi satu-satunya bagian yang "secara optimal" dapat diterapkan ke indeks menggunakan $all operator kueri dalam semua kasus. Logika penting yang tersisa sebenarnya berlaku "setelah" ekspresi utama dievaluasi dan "di samping" agar tidak ada hasil yang dikembalikan selain yang memenuhi ekspresi dengan $expr atau $where .

Logika dasar masing-masing pada dasarnya adalah untuk mengekstrak nilai "index" properti dari anggota array "pertama" yang benar-benar cocok dengan nilai masing-masing dalam "value" Properti. Dimana ini adalah "kurang dari", maka kondisinya adalah true dan ini memenuhi dokumen yang dikembalikan.

Jadi perhatikan bahwa "evaluasi yang dihitung" cocok dengan efisiensi operator kueri, dan tanpa digunakan "dalam kombinasi" dari kondisi operator kueri lain yang dapat mengakses "indeks", maka "pemindaian koleksi lengkap" akan dimulai.

Tetapi hasil keseluruhan tentu lebih efisien daripada mengembalikan semua item yang cocok ke kondisi kueri pertama dan kemudian menolaknya pada kursor "setelah" kembali dari database.

Lihat juga dokumentasi untuk $arrayElemAt , $indexOfArray , $lt dan Array.find() untuk JavaScript




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. bagaimana cara menggunakan grup di pymongo untuk mengelompokkan baris yang serupa?

  2. Bagaimana cara memasukkan elemen ke daftar internal MongoDB?

  3. Cara Membuat Indeks dengan Nama Tertentu di MongoDB

  4. Agregasi MongoDB dengan $lookup hanya menyertakan (atau memproyeksikan) beberapa bidang untuk dikembalikan dari kueri

  5. Layanan Mongodb tidak dapat dimulai