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

Kueri dan Sisipkan dengan satu perintah

Kueri tidak serumit yang terlihat pada awalnya - kueri untuk menemukan semua dokumen yang "tumpang tindih" dengan rentang yang Anda berikan adalah:

db.test.find( { "startTime" : { "$lt" : new_end_time }, 
                "endTime"   : { "$gt": new_start_time } 
            } 
)

Ini akan mencocokkan dokumen apa pun dengan tanggal mulai lebih awal dari tanggal akhir kami dan tanggal akhir lebih besar dari waktu mulai kami. Jika Anda memvisualisasikan rentang sebagai titik pada garis:

-----|*********|----------|****|-----------|******||********|---
    s1         e1         s2   e2         s3     e3s4       e4

pasangan sX-eX mewakili rentang yang ada. Jika Anda mengambil s5-e5 baru, Anda dapat melihat bahwa jika kita menghilangkan pasangan yang dimulai setelah tanggal akhir kami (mereka tidak dapat tumpang tindih dengan kami) dan kemudian kami menghilangkan semua pasangan yang berakhir sebelum tanggal mulai kami, jika kami tidak memiliki apa-apa lagi, maka kami baik untuk memasukkan.

Kondisi itu akan melakukan penyatuan semua dokumen dengan tanggal akhir $lte awal kami dan yang memiliki tanggal mulai $gte milik kami mencakup semua dokumen yang sudah ada dalam koleksi. Permintaan kami membalik ini untuk memastikan bahwa tidak ada dokumen yang memenuhi kebalikan dari kondisi ini.

Di sisi kinerja, sangat disayangkan bahwa Anda hanya menyimpan tanggal sebagai string. Jika Anda menyimpannya sebagai stempel waktu (atau nomor apa pun, sungguh), Anda dapat membuat kueri ini menggunakan indeks dengan lebih baik. Karena itu, untuk kinerja Anda ingin memiliki indeks di { "startTime":1, "endTime":1 } .

Sangat mudah untuk menemukan apakah rentang yang ingin Anda sisipkan tumpang tindih dengan rentang yang ada, tetapi untuk pertanyaan kedua Anda:

Tidak ada cara yang tepat untuk melakukannya dengan sisipan karena mereka tidak mengambil kueri (yaitu tidak bersyarat).

Namun, Anda dapat menggunakan pembaruan dengan kondisi upsert. Itu dapat menyisipkan jika kondisinya tidak cocok dengan apa pun, tetapi jika cocok, ia akan mencoba memperbarui dokumen yang cocok!

Jadi trik yang akan Anda gunakan adalah membuat pembaruan menjadi noop, dan mengatur bidang yang Anda butuhkan hanya pada upsert. Sejak 2.4 ada $setOnInsert operator untuk memperbarui. Hal lengkapnya akan terlihat seperti ini:

db.test.update( 
   { startTime: { "$lt" : new_end_time }, "endTime" : { "$gt": new_start_time } }, 
   { $setOnInsert:{ startTime:new_start_time, endTime: new_end_time}},
   {upsert:1}
)
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("538e0f6e7110dddea4383938")
})
db.test.update(
   { startTime:{ "$lt" : new_end_time }, "endTime" : { "$gt": new_start_time } },
   { $setOnInsert:{ startTime:new_start_time, endTime: new_end_time}},
   {upsert:1}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

Saya baru saja melakukan "pembaruan" yang sama dua kali - pertama kali, tidak ada dokumen yang tumpang tindih sehingga pembaruan melakukan "upsert" yang dapat Anda lihat di WriteResult itu kembali.

Ketika saya menjalankannya untuk kedua kalinya, itu akan tumpang tindih (tentu saja sendiri) sehingga mencoba memperbarui dokumen yang cocok, tetapi melihat tidak ada pekerjaan yang harus dilakukan. Anda dapat melihat nMatched yang dikembalikan adalah 1 tetapi tidak ada yang dimasukkan atau diubah.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Urutan terbalik item yang ditarik dari database di ng-repeat

  2. Nanodetik hilang dari MongoDB ISODate Object

  3. MongoDB DBRef PADA HAPUS CASCADE

  4. Tarik MongoDB Java

  5. Bagaimana cara mendapatkan data ReferenceField di mongoengine?