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

Bagaimana menemukan dokumen dan subdokumen tunggal yang cocok dengan kriteria yang diberikan dalam koleksi MongoDB

Apa yang Anda cari adalah posisi $ operator dan "proyeksi". Untuk satu bidang Anda harus mencocokkan elemen larik yang diperlukan menggunakan "notasi titik", untuk lebih dari satu bidang gunakan $elemMatch :

db.products.find(
    { "items.date": "31.08.2014" },
    { "shop": 1, "name":1, "items.$": 1 }
)

Atau $elemMatch untuk lebih dari satu bidang yang cocok:

db.products.find(
    { "items":  { 
        "$elemMatch": { "date": "31.08.2014",  "purchasePrice": 1 }
    }},
    { "shop": 1, "name":1, "items.$": 1 }
)

Ini hanya berfungsi untuk elemen array tunggal dan hanya satu yang akan dikembalikan. Jika Anda ingin lebih dari satu elemen larik dikembalikan dari kondisi Anda, maka Anda memerlukan penanganan lebih lanjut dengan kerangka kerja agregasi.

db.products.aggregate([
    { "$match": { "items.date": "31.08.2014" } },
    { "$unwind": "$items" },
    { "$match": { "items.date": "31.08.2014" } },
    { "$group": {
        "_id": "$_id",
        "shop": { "$first": "$shop" },
        "name": { "$first": "$name" },
        "items": { "$push": "$items" }
    }}
])

Atau mungkin dalam bentuk yang lebih pendek/lebih cepat sejak MongoDB 2.6 di mana array item Anda berisi entri unik:

db.products.aggregate([
    { "$match": { "items.date": "31.08.2014" } },
    { "$project": {
        "shop": 1,
        "name": 1,
        "items": {
            "$setDifference": [
                { "$map": {
                    "input": "$items",
                    "as": "el",
                    "in": {
                        "$cond": [
                            { "$eq": [ "$$el.date", "31.08.2014" ] },
                            "$$el",
                            false 
                        ]
                    }
                }},
                [false]
            ]
        }
    }}
])

Atau mungkin dengan $redact , tapi sedikit dibuat-buat:

db.products.aggregate([
    { "$match": { "items.date": "31.08.2014" } },
    { "$redact": {
        "$cond": [
             { "$eq": [ { "$ifNull": [ "$date", "31.08.2014" ] }, "31.08.2014" ] },
             "$$DESCEND",
             "$$PRUNE"
         ]
    }}
])

Lebih modern, Anda akan menggunakan $filter :

db.products.aggregate([
  { "$match": { "items.date": "31.08.2014" } },
  { "$addFields": {
    "items": {
      "input": "$items",
      "cond": { "$eq": [ "$$this.date", "31.08.2014" ] }
    }
  }}
])

Dan dengan beberapa kondisi, $elemMatch dan $and dalam $filter :

db.products.aggregate([
  { "$match": { 
    "$elemMatch": { "date": "31.08.2014",  "purchasePrice": 1 }
  }},
  { "$addFields": {
    "items": {
      "input": "$items",
      "cond": { 
        "$and": [
          { "$eq": [ "$$this.date", "31.08.2014" ] },
          { "$eq": [ "$$this.purchasePrice", 1 ] }
        ]
      }
    }
  }}
])

Jadi itu hanya tergantung pada apakah Anda selalu mengharapkan satu elemen cocok atau beberapa elemen, dan kemudian pendekatan mana yang lebih baik. Tetapi jika memungkinkan .find() metode umumnya akan lebih cepat karena tidak memiliki overhead dari operasi lain, yang pada formulir terakhir tidak tertinggal jauh di belakang sama sekali.

Sebagai catatan tambahan, "tanggal" Anda direpresentasikan sebagai string yang bukan ide yang bagus untuk kedepannya. Pertimbangkan untuk mengubahnya menjadi Tanggal yang tepat jenis objek, yang akan sangat membantu Anda di masa mendatang.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB:Bagaimana cara menanyakan deret waktu dengan data yang tidak lengkap?

  2. Pemodelan data multibahasa di MongoDB

  3. Alamofire dengan masalah koneksi localhost

  4. Bagaimana saya bisa menambahkan string ke setiap nilai dalam array di Mongoose?

  5. Apakah mongodb secara otomatis membuat indeks pada bidang _id dari dokumen yang disematkan?