Setiap hari, saya menerima stok dokumen (pembaruan). Yang ingin saya lakukan adalah memasukkan setiap item yang belum ada.
- Saya juga ingin melacak saat pertama kali saya memasukkannya, dan terakhir kali saya melihatnya dalam pembaruan.
- Saya tidak ingin memiliki dokumen duplikat.
- Saya tidak ingin menghapus dokumen yang sebelumnya telah disimpan, tetapi tidak ada dalam pembaruan saya.
- 95% (diperkirakan) dari catatan tidak dimodifikasi dari hari ke hari.
Saya menggunakan driver Python (pymongo).
Apa yang saya lakukan saat ini adalah (pseudo-code):
for each document in update:
existing_document = collection.find_one(document)
if not existing_document:
document['insertion_date'] = now
else:
document = existing_document
document['last_update_date'] = now
my_collection.save(document)
Masalah saya adalah sangat lambat (40 menit untuk kurang dari 100.000 catatan, dan saya memiliki jutaan dari mereka dalam pembaruan). Saya cukup yakin ada sesuatu yang dibangun untuk melakukan ini, tetapi dokumen untuk pembaruan () adalah mmmhhh .... agak singkat .... ( http://www.mongodb.org/display/DOCS/Updating )
Adakah yang bisa menyarankan cara melakukannya dengan lebih cepat?
Pada MongoDB 2.4, Anda dapat menggunakan $ setOnInsert ( http://docs.mongodb.org/manual/reference/operator/setOnInsert/ )
Set 'insertion_date' menggunakan $ setOnInsert dan 'last_update_date' menggunakan $ set pada perintah upsert Anda.
Untuk mengubah kodesemu menjadi contoh yang berfungsi:
sumber
Anda selalu dapat membuat indeks unik, yang menyebabkan MongoDB menolak penyimpanan yang bertentangan. Pertimbangkan hal-hal berikut yang dilakukan dengan menggunakan shell mongodb:
sumber
Anda dapat menggunakan Upsert dengan operator $ setOnInsert.
sumber
1. Gunakan Pembaruan.
Menggambar dari jawaban Van Nguyen di atas, gunakan pembaruan alih-alih menyimpan. Ini memberi Anda akses ke opsi yang aktif.
CATATAN : Metode ini mengesampingkan seluruh dokumen saat ditemukan ( Dari dokumen )
1.a. Gunakan $ set
Jika Anda ingin memperbarui pilihan dokumen, tetapi tidak semuanya, Anda dapat menggunakan metode $ set dengan pembaruan. (lagi, Dari dokumen ) ... Jadi, jika Anda ingin mengatur ...
Kirimkan sebagai ...
Ini membantu mencegah secara tidak sengaja menimpa semua dokumen Anda
{ name: 'jason borne' }
.sumber
Ringkasan
Catatan, saya menduga PyMongo, ubah sesuai dengan bahasa pilihan Anda.
Instruksi:
Buat koleksi dengan indeks dengan unique = true sehingga Anda tidak mendapatkan catatan duplikat.
Iterate atas catatan input Anda, buat batch mereka 15.000 catatan atau lebih. Untuk setiap catatan dalam kumpulan, buat dikt yang terdiri dari data yang ingin Anda masukkan, anggap masing-masing akan menjadi catatan baru. Tambahkan cap waktu 'dibuat' dan 'diperbarui' ke ini. Terbitkan ini sebagai perintah penyisipan batch dengan flag 'LanjutkanOnError' = benar, sehingga penyisipan semua yang lain terjadi bahkan jika ada kunci duplikat di sana (yang sepertinya akan ada). INI AKAN TERJADI SANGAT CEPAT. Menyisipkan massal rock, saya mendapatkan level kinerja 15k / detik. Catatan lebih lanjut tentang ContinueOnError, lihat http://docs.mongodb.org/manual/core/write-operations/
Rekaman sisipan terjadi SANGAT cepat, jadi Anda akan selesai dengan sisipan itu dalam waktu singkat. Sekarang, saatnya untuk memperbarui catatan yang relevan. Lakukan ini dengan pengambilan batch, jauh lebih cepat dari satu per satu.
Ulangi semua catatan input Anda lagi, buat kumpulan 15K atau lebih. Ekstrak kunci (terbaik jika ada satu kunci, tetapi tidak dapat membantu jika tidak ada). Ambil kumpulan rekaman ini dari Mongo dengan permintaan db.collectionNameBlah.find ({field: {$ in: [1, 2,3 ...}). Untuk setiap catatan ini, tentukan apakah ada pembaruan, dan jika demikian, keluarkan pembaruan, termasuk memperbarui cap waktu yang 'diperbarui'.
Sayangnya, kita harus mencatat, MongoDB 2.4 dan di bawah ini TIDAK termasuk operasi pembaruan massal. Mereka sedang mengerjakannya.
Poin Optimalisasi Kunci:
sumber
Saya tidak berpikir mongodb mendukung jenis uperting selektif ini. Saya memiliki masalah yang sama dengan LeMiz, dan menggunakan pembaruan (kriteria, newObj, upsert, multi) tidak berfungsi dengan baik ketika berhadapan dengan stempel waktu 'dibuat' dan 'diperbarui'. Diberikan pernyataan upert berikut:
Skenario # 1 - dokumen dengan 'nama' dari 'abc' tidak ada: Dokumen baru dibuat dengan 'nama' = 'abc', 'dibuat' = 2010-07-14 11:11:11, dan 'diperbarui' = 2010-07-14 11:11:11.
Skenario # 2 - dokumen dengan 'nama' dari 'abc' sudah ada dengan yang berikut ini: 'name' = 'abc', 'Created' = 2010-07-12 09:09:09, dan 'updated' = 2010-07 -13 10:10:10. Setelah upert, dokumen sekarang akan sama dengan hasil dalam skenario # 1. Tidak ada cara untuk menentukan dalam bidang mana yang disetel jika memasukkan, dan bidang mana yang dibiarkan sendiri jika diperbarui.
Solusi saya adalah membuat indeks unik pada bidang kritera , melakukan penyisipan, dan segera setelah itu melakukan pembaruan hanya di bidang 'diperbarui'.
sumber
Secara umum, menggunakan pembaruan lebih baik di MongoDB karena hanya akan membuat dokumen jika belum ada, meskipun saya tidak yakin bagaimana cara kerjanya dengan adaptor python Anda.
Kedua, jika Anda hanya perlu tahu apakah dokumen itu ada atau tidak, hitung () yang mengembalikan hanya angka akan menjadi pilihan yang lebih baik daripada find_one yang seharusnya mentransfer seluruh dokumen dari MongoDB Anda yang menyebabkan lalu lintas yang tidak perlu.
sumber