Apakah mungkin untuk ObjectId Mongo yang sama persis dihasilkan untuk dokumen dalam dua koleksi yang berbeda? Saya menyadari bahwa itu sangat tidak mungkin, tetapi apakah itu mungkin?
Tanpa terlalu spesifik, alasan saya bertanya adalah bahwa dengan aplikasi yang saya kerjakan kami menunjukkan profil publik pejabat terpilih yang kami harap dapat dikonversi menjadi pengguna situs kami yang lengkap. Kami memiliki koleksi terpisah untuk pengguna dan pejabat terpilih yang saat ini tidak menjadi anggota situs kami. Ada berbagai dokumen lain yang berisi berbagai potongan data tentang pejabat terpilih yang semuanya memetakan kembali ke orang tersebut menggunakan ObjectId resmi terpilih mereka.
Setelah membuat akun, kami masih menyoroti data yang terkait dengan pejabat terpilih tetapi sekarang mereka juga merupakan bagian dari koleksi pengguna dengan ObjectId pengguna yang sesuai untuk memetakan profil mereka untuk berinteraksi dengan aplikasi kami.
Kami telah mulai mengonversi aplikasi kami dari MySql ke Mongo beberapa bulan yang lalu dan sementara kami dalam transisi, kami menyimpan id MySql lama untuk kedua tipe data ini dan kami juga mulai sekarang menyimpan ObjectId resmi Mongo yang terpilih di pengguna. mendokumentasikan untuk memetakan kembali ke data resmi terpilih.
Saya sedang merenungkan hanya menetapkan ObjectId pengguna baru sebagai ObjectId resmi terpilih sebelumnya untuk membuat hal-hal lebih sederhana tetapi ingin memastikan bahwa itu tidak mungkin untuk memiliki tabrakan dengan ObjectId pengguna yang ada.
Terima kasih atas wawasan Anda.
Sunting: Tidak lama setelah memposting pertanyaan ini, saya menyadari bahwa solusi yang saya usulkan bukanlah ide yang sangat bagus. Akan lebih baik untuk menjaga skema saat ini yang kami miliki dan hanya tautan ke '_id' resmi yang terpilih dalam dokumen pengguna.
Jawaban:
Jawaban singkat
Hanya untuk menambahkan jawaban langsung ke pertanyaan awal Anda: YA, jika Anda menggunakan generasi ID Objek BSON, maka untuk sebagian besar driver ID hampir pasti akan menjadi unik di seluruh koleksi. Lihat di bawah untuk arti "hampir pasti".
Jawaban panjang
ID Objek BSON yang dihasilkan oleh driver Mongo DB sangat mungkin unik di seluruh koleksi. Ini terutama karena 3 byte terakhir dari ID, yang untuk sebagian besar driver dihasilkan melalui penghitung kenaikan statis. Penghitung itu tidak bergantung pada pengumpulan; ini global. Driver Java, misalnya, menggunakan AtomicInteger statis yang diinisialisasi secara acak.
Jadi mengapa, dalam dokumen Mongo, apakah mereka mengatakan bahwa ID "sangat mungkin" menjadi unik, bukannya langsung mengatakan bahwa mereka AKAN unik? Tiga kemungkinan dapat terjadi di mana Anda tidak akan mendapatkan ID unik (beri tahu saya jika ada lebih banyak):
Sebelum diskusi ini, ingat bahwa ID Objek BSON terdiri dari:
[4 byte detik sejak zaman, hash mesin 3 byte, ID proses 2 byte, penghitung 3 byte]
Berikut adalah tiga kemungkinan, jadi Anda menilai sendiri seberapa besar kemungkinan mendapatkan dupe:
1) Counter overflow: ada 3 byte di konter. Jika Anda memasukkan lebih dari 16.777.216 (2 ^ 24) dokumen dalam satu detik, pada mesin yang sama, dalam proses yang sama, maka Anda dapat melimpahi byte kenaikan counter dan berakhir dengan dua ID Obyek yang berbagi waktu yang sama, mesin , memproses, dan melawan nilai.
2) Counter non-incrementing: beberapa driver Mongo menggunakan angka acak alih-alih menambah angka untuk byte counter. Dalam kasus ini, ada peluang 1 / 16.777.216 untuk menghasilkan ID yang tidak unik, tetapi hanya jika kedua ID tersebut dihasilkan dalam detik yang sama (yaitu sebelum bagian waktu dari ID diperbarui ke detik berikutnya), pada saat yang sama mesin, dalam proses yang sama.
3) Mesin dan proses hash dengan nilai yang sama. ID mesin dan nilai ID proses dapat, dalam beberapa skenario yang sangat tidak mungkin, dipetakan ke nilai yang sama untuk dua mesin yang berbeda. Jika ini terjadi, dan pada saat yang sama kedua penghitung pada dua mesin yang berbeda, pada detik yang sama, menghasilkan nilai yang sama, maka Anda akan berakhir dengan duplikat ID.
Ini adalah tiga skenario yang harus diperhatikan. Skenario 1 dan 3 tampaknya sangat tidak mungkin, dan skenario 2 benar-benar dapat dihindari jika Anda menggunakan driver yang tepat. Anda harus memeriksa sumber driver untuk mengetahui dengan pasti.
sumber
ObjectId
seperti sebelumnya selama hash mesin, memproses ID, dan melawan semuanya ternyata samaObjectIds dihasilkan sisi klien dengan cara yang mirip dengan UUID tetapi dengan beberapa properti yang lebih baik untuk penyimpanan dalam database seperti peningkatan pesanan secara kasar dan penyandian waktu pembuatannya secara gratis. Kuncinya untuk use case Anda adalah mereka dirancang untuk menjamin keunikan dengan probabilitas tinggi bahkan jika mereka dihasilkan pada mesin yang berbeda.
Sekarang jika Anda merujuk ke bidang _id secara umum, kami tidak memerlukan keunikan di seluruh koleksi sehingga aman untuk menggunakan kembali _id yang lama. Sebagai contoh konkret, jika Anda memiliki dua koleksi,
colors
danfruits
, keduanya secara bersamaan dapat memiliki objek seperti{_id: 'orange'}
.Jika Anda ingin tahu lebih banyak tentang bagaimana ObjectIds dibuat, berikut adalah spesifikasinya: http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-BSONObjectIDSpecification
sumber
Jika ada yang mengalami masalah dengan duplikat Objecto Mongo, Anda harus tahu bahwa meskipun kemungkinan dups terjadi di Mongo itu sendiri, ada kemungkinan duplikat _id dihasilkan dengan PHP dalam bahasa Mongo.
Kasus penggunaan di mana hal ini terjadi dengan keteraturan bagi saya adalah ketika saya mengulang-ulang data dan mencoba menyuntikkan data ke dalam koleksi.
Array yang menyimpan data injeksi harus secara eksplisit diatur ulang pada setiap iterasi - bahkan jika Anda tidak menentukan nilai _id. Untuk beberapa alasan, proses INSERT menambahkan Mongo _id ke array seolah-olah itu adalah variabel global (bahkan jika array tidak memiliki cakupan global). Ini dapat mempengaruhi Anda bahkan jika Anda memanggil penyisipan dalam panggilan fungsi terpisah di mana Anda biasanya mengharapkan nilai-nilai array tidak bertahan kembali ke fungsi panggilan.
Ada tiga solusi untuk ini:
unset()
bidang _id dari arrayarray()
setiap kali Anda mengulang datasetDugaan saya adalah bahwa ini adalah bug di antarmuka PHP, dan bukan masalah dengan Mongo, tetapi jika Anda mengalami masalah ini, hapus saja _id dan Anda harus baik-baik saja.
sumber
Tidak ada jaminan apa pun tentang keunikan ObjectId di seluruh koleksi. Bahkan jika secara probabilistik sangat tidak mungkin, itu akan menjadi desain aplikasi yang sangat buruk yang mengandalkan keunikan _id di koleksi.
Seseorang dapat dengan mudah menguji ini di shell mongo:
Jadi, benar-benar tidak bergantung pada _id yang unik di seluruh koleksi, dan karena Anda tidak mengontrol fungsi pembuatan ObjectId, jangan bergantung padanya.
Dimungkinkan untuk membuat sesuatu yang lebih seperti uuid, dan jika Anda melakukannya secara manual, Anda bisa memiliki jaminan keunikan yang lebih baik.
Ingatlah bahwa Anda dapat meletakkan objek "jenis" yang berbeda dalam koleksi yang sama, jadi mengapa tidak hanya menempatkan dua "tabel" Anda di koleksi yang sama. Mereka akan berbagi ruang _id yang sama, dan dengan demikian, akan dijamin unik. Beralih dari "calon" ke "terdaftar" akan menjadi membalik sederhana bidang ...
sumber