Saya mencoba membiarkan MongoDB mendeteksi nilai duplikat berdasarkan indeksnya. Saya pikir ini mungkin terjadi di MongoDB, tetapi melalui pembungkus Mongoose hal-hal tampaknya rusak. Jadi untuk sesuatu seperti ini:
User = new Schema ({
email: {type: String, index: {unique: true, dropDups: true}}
})
Saya dapat menyelamatkan 2 pengguna dengan email yang sama. Menisik.
Masalah yang sama telah diungkapkan di sini: https://github.com/LearnBoost/mongoose/issues/56 , tetapi utas itu sudah lama dan tidak mengarah ke mana pun.
Untuk saat ini, saya secara manual melakukan panggilan ke db untuk menemukan pengguna. Panggilan itu tidak mahal karena "email" diindeks. Tapi akan menyenangkan membiarkannya ditangani secara asli.
Apakah ada yang punya solusi untuk ini?
Jawaban:
Ups! Anda hanya perlu memulai ulang mongo.
sumber
Dan indeks ulang juga, dengan:
Dalam pengujian, karena saya tidak memiliki data penting, Anda juga dapat melakukan:
sumber
Saya mengalami masalah yang sama: Saya menambahkan batasan unik untuk
email
bidang tersebut ke kamiUserSchema
setelah menambahkan pengguna ke db, dan masih dapat menyelamatkan pengguna dengan email penipuan. Saya menyelesaikan ini dengan melakukan hal berikut:1) Hapus semua dokumen dari koleksi pengguna.
2) Dari shell mongo, jalankan perintah:
db.users.createIndex({email: 1}, {unique: true})
Mengenai langkah 1, perhatikan bahwa dari dokumen Mongo:
https://docs.mongodb.com/manual/core/index-unique/
sumber
Perilaku ini juga terjadi jika Anda meninggalkan beberapa duplikat di Mongo. Mongoose akan mencoba membuatnya di Mongo saat aplikasi Anda dijalankan.
Untuk mencegahnya, Anda dapat menangani kesalahan ini dengan cara ini:
yourModel.on('index', function(err) { if (err?) { console.error err } );
sumber
Oke, saya bisa menyelesaikan ini dari mongoshell dengan menambahkan indeks di lapangan dan mengatur properti unik:
db.<collectionName>.ensureIndex({fieldName: 1}, {unique: true});
Shell harus merespons dengan cara ini:
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
Sekarang untuk menguji dengan cepat dari mongoshell:
var doc = {fieldName: 'abc'}; db.<collectionName>.insert(doc)
Harus memberikan: WriteResult ({"nInserted": 1})
Tapi saat mengulang lagi:
Akan memberi:
WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: fuelConsumption.users.$email_1 dup key: { : \"[email protected]\" }" } })
sumber
Saya telah melakukan sesuatu seperti ini:
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const FooSchema = new Schema({ name: { type: String, required: true, index: true, unique: true } }); const Foo = mongoose.model('Foo', FooSchema); Foo.createIndexes(); module.exports = Foo
Saya menambahkan
Foo.createIndexes()
baris bc. Saya mendapatkan peringatan penghentian berikut saat kode sedang dijalankan:(node:21553) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.
Saya tidak yakin apakah
Foo.createIndexes()
asynchronous, tetapi AFAIK tampaknya berfungsi dengan baiksumber
index: true
untuk membuat indeks unik saya.Menurut dokumentasi: https://docs.mongodb.com/v2.6/tutorial/modify-an-index/
JANGAN MULAI ULANG LAGU!
1 - jatuhkan koleksinya
2 - indeks ulang tabel
db.users.ensureIndex({email: 1, type: 1}, {unique: true})
sumber
Mongoose sedikit longgar saat menerapkan indeks unik dari level aplikasi; oleh karena itu, lebih disukai untuk menerapkan indeks unik Anda dari database itu sendiri menggunakan mongo cli atau secara eksplisit memberi tahu mongoose bahwa Anda serius tentang
unique
indeks dengan menulis baris kode berikut tepat setelah UserSchema Anda:UserSchema.index({ username: 1, email: 1 }, { unique: true});
Ini akan memberlakukan indeks unik di kedua kolom
username
danemail
di UserSchema Anda. Bersulang.sumber
Mongoose diam-diam akan gagal menambahkan indeks unik jika:
Dalam kasus pertama, daftarkan indeks dengan
db.collection.getIndexes()
, dan hapus indeks lama dengandb.collection.dropIndex("index_name")
. Saat Anda memulai ulang aplikasi Mongoose, itu harus menambahkan indeks baru dengan benar.Dalam kasus kedua, Anda perlu menghapus duplikat sebelum memulai ulang aplikasi Mongoose.
sumber
luwak-unik-validator
Cara menggunakan plugin ini:
1) npm install --save mongoose-unique-validator
2) dalam skema Anda, ikuti panduan ini:
// declare this at the top var mongoose = require('mongoose'); var uniqueValidator = require('mongoose-unique-validator'); // exampleSchema = mongoose.Schema({}) etc... exampleSchema.plugin(uniqueValidator); // module.exports = mongoose.model(...) etc....
3) metode luwak
Saat menggunakan metode seperti
findOneAndUpdate
Anda harus meneruskan objek konfigurasi ini:{ runValidators: true, context: 'query' }
ie. User.findOneAndUpdate( { email: '[email protected]' }, { email: '[email protected]' }, { runValidators: true, context: 'query' }, function(err) { // ... }
4) opsi tambahan
case insensitive
gunakan opsi uniqueCaseInsensitive di skema Anda
ie. email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }
pesan kesalahan khusus
ie. exampleSchema.plugin(uniqueValidator, { message: 'Error, expected {PATH} to be unique.' });
Sekarang Anda dapat menambahkan / menghapus properti unik ke skema Anda tanpa khawatir harus memulai ulang mongo, menjatuhkan database, atau membuat indeks.
Peringatan (dari dokumen):
Karena kami mengandalkan operasi asinkron untuk memverifikasi apakah sebuah dokumen ada dalam database, dua kueri dapat dieksekusi pada saat yang sama, keduanya mendapatkan 0 kembali, lalu keduanya dimasukkan ke dalam MongoDB.
Selain mengunci koleksi secara otomatis atau memaksa koneksi tunggal, tidak ada solusi nyata.
Bagi sebagian besar pengguna kami, ini tidak akan menjadi masalah, tetapi merupakan kasus tepi yang harus diperhatikan.
sumber
Jawaban terbaru: tidak perlu me-restart mongodb sama sekali, jika colleciton sudah memiliki indeks nama yang sama, luwak tidak akan membuat ulang indeks Anda lagi, jadi, jatuhkan indeks colleciton yang ada terlebih dahulu, dan sekarang, ketika Anda menjalankan mongoose, itu akan membuat indeks baru , proses di atas memecahkan masalah saya.
sumber
Anda juga dapat mengatasi masalah ini dengan menghapus indeks;
anggaplah Anda ingin menghapus indeks unik dari collection
users
dan fieldusername
, ketikkan ini:db.users.dropIndex('username_1');
sumber
Jika tabel / koleksi kosong, buat indeks unik untuk bidang tersebut:
db.<collection_name>.createIndex({'field':1}, {unique: true})
Jika tabel / koleksi tidak kosong, letakkan koleksi dan buat indeks:
db.<collection_name>.drop() db.<collection_name>.createIndex({'field':1}, {unique: true})
Sekarang mulai ulang mongoDB.
sumber
periksa apakah autoIndex dalam skema benar, mungkin disetel salah (default benar) saat Anda menggunakan opsi mongoose.connect
sumber
Saya menghadapi masalah yang sama untuk sementara dan melakukan banyak pencarian dan solusi untuk saya adalah
createIndexes()
fungsinya.Saya berharap itu membantu.
jadi kodenya akan seperti itu.
User = new Schema ({ email: {type: String, unique: true} }); User.createIndexes();
sumber
Jika Anda menggunakan opsi
autoIndex: false
dalam metode koneksi seperti ini:mongoose.connect(CONNECTION_STRING, { autoIndex: false });
Coba hapus itu. Jika itu tidak berhasil, coba restart mongodb seperti yang disarankan di utas ini.
sumber
Anda dapat menentukan skema Anda sebagai
User = new Schema ({ email: { type: String, unique: true } })
Tetapi mungkin ini tidak akan berfungsi ketika sudah ada dokumen dan setelah itu, Anda telah mengubah skema Pengguna. Anda dapat membuat indeks pada email untuk Koleksi pengguna ini jika Anda tidak ingin menghapus koleksi. Dengan menggunakan perintah ini Anda dapat membuat indeks di email.
db.User.createIndex({email:1},{unique: true})
Atau Anda bisa melepaskan koleksi dan menambahkan pengguna lagi.
Untuk menjatuhkan koleksi, Anda dapat memasukkan ini:
sumber
Ketika saya mengalami masalah ini, saya mencoba menjatuhkan database, memulai ulang server (nodemon) berkali-kali dan tidak ada trik yang tidak berfungsi sama sekali. Saya menemukan pekerjaan berikut, melalui Robo 3T:
_id_
sebagai default. Sekarang, pilih Tambah Indeksemail
untuk bidang email, misalnyaBerikan Kunci sebagai JSON. Sebagai contoh
{ "email": 1 }
Klik pada kotak centang Unik
Ini akan memastikan tidak ada email duplikat yang disimpan di MongoDB.
sumber
Pastikan koleksi Anda tidak memiliki bidang yang berlebihan tempat Anda baru saja memasukkan indeks unik.
Kemudian mulai ulang aplikasi Anda (luwak). Itu hanya diam-diam menambahkan indeks gagal.
sumber
Menghapus semua dokumen dari koleksi:
Dan restart, seperti yang disebutkan orang lain, berhasil untuk saya
sumber
Jika MongoDB Anda berfungsi sebagai layanan (cara mudah menemukannya adalah jika Anda tidak perlu terhubung ke database tanpa memulai file mongod.exe melalui terminal), maka setelah melakukan perubahan, Anda mungkin perlu memulai ulang layanan dan / atau jatuhkan database Anda sepenuhnya.
Ini cukup aneh karena untuk beberapa pengguna hanya menjatuhkan satu koleksi yang berhasil. Beberapa dari mereka hanya perlu menjatuhkan database. Tapi itu tidak berhasil untuk saya. Saya menjatuhkan database, lalu memulai ulang layanan Server MongoDB.
Untuk memulai kembali Layanan, pencarian Layanan di bilah pencarian Windows kemudian temukan layanan MongoDB, klik dua kali untuk membuka lalu berhenti dan mulai layanan lagi.
Jika metode lain tidak berhasil untuk Anda, saya yakin ini akan berhasil.
sumber
Dalam kasus saya, luwak sudah ketinggalan zaman. saya memeriksanya dengan menjalankan npm usang di CMD. dan memperbarui 'luwak'.
Tolong beri tahu apakah itu berhasil untuk Anda juga.
sumber
Ketika Anda menghubungkan database Anda dengan aplikasi, tambahkan opsi ini: "audoIndex: true" misalnya dalam kode saya, saya melakukan ini:
const options = { // your options go here ... // this code is the solution audoIndex: true } mongoose.connect(DB_URI, options);
Saya juga membuang koleksi yang bermasalah dan membuatnya kembali untuk memastikannya berfungsi. Saya menemukan solusi ini di: https://dev.to/emmysteven/solved-mongoose-unique-index-not-working-45d5 Saya juga mencoba solusi seperti "restart MongoDB" tetapi tidak berhasil untuk saya.
sumber