E11000 ดัชนีข้อผิดพลาดที่สำคัญที่ซ้ำกันใน mongodb mongoose


228

ต่อไปนี้เป็นuserสคีมาของฉันในuser.jsแบบ -

var userSchema = new mongoose.Schema({
    local: {
        name: { type: String },
        email : { type: String, require: true, unique: true },
        password: { type: String, require:true },
    },
    facebook: {
        id           : { type: String },
        token        : { type: String },
        email        : { type: String },
        name         : { type: String }
    }
});

var User = mongoose.model('User',userSchema);

module.exports = User;

นี่คือวิธีที่ฉันใช้มันในคอนโทรลเลอร์ของฉัน -

var user = require('./../models/user.js');

นี่คือวิธีที่ฉันบันทึกไว้ใน db -

user({'local.email' : req.body.email, 'local.password' : req.body.password}).save(function(err, result){
    if(err)
        res.send(err);
    else {
        console.log(result);
        req.session.user = result;
        res.send({"code":200,"message":"Record inserted successfully"});
    }
});

ข้อผิดพลาด -

{"name":"MongoError","code":11000,"err":"insertDocument :: caused by :: 11000 E11000 duplicate key error index: mydb.users.$email_1  dup key: { : null }"} 

ฉันตรวจสอบคอลเลกชัน db และไม่มีรายการที่ซ้ำกันอยู่ให้ฉันรู้ว่าฉันกำลังทำอะไรผิดหรือเปล่า?

FYI - req.body.emailและreq.body.passwordกำลังดึงค่า

ฉันตรวจสอบโพสต์นี้ด้วย แต่ไม่ช่วยลิงก์ STACK

หากฉันลบอย่างสมบูรณ์มันจะแทรกเอกสารมิฉะนั้นจะเกิดข้อผิดพลาด "ซ้ำ" ข้อผิดพลาดแม้ว่าฉันจะมีรายการอยู่ในเครื่อง


1
มีข้อผิดพลาดเดียวกัน! ในระหว่างการพัฒนาเราปิดใช้งานการจัดทำดัชนีอัตโนมัติและใช้ชื่อ / คีย์สคีมาเล็ก ๆ ในภายหลังเราตัดสินใจใช้ TitleCase แทน แต่ไม่สามารถอัปเดตชื่อดัชนีของเรา (เช่น: titleCase แทน TitleCase) ดังนั้นเมื่อเราเปิดใช้งานการจัดทำดัชนีเราได้รับข้อผิดพลาดนี้ ใช้เวลาสักครู่เพื่อคิดออก คุณจะต้องแน่ใจว่าชื่อ / คีย์ทั้งหมดมีชื่อทุกที่
Jeach

6
ฉันมีข้อผิดพลาดเดียวกันและตั้งค่าโมเดลพังพอนให้unique: falseไม่มีผลกระทบใด ๆ ฉันรู้ว่าฉันต้องวางโต๊ะก่อนจากนั้นก็ใช้งานได้ db.whateverthecollection.drop({})คุณสามารถทำเช่น seomthing ระวังมันลบคอลเลกชัน
Pere

1
_id: mongoose.Types.ObjectId เพิ่มเนื่องจากต้องการรหัสที่ไม่ซ้ำกัน
Mayank Pandav

คำตอบ:


239

ข้อความแสดงข้อผิดพลาดบอกว่ามีการบันทึกnullเป็นอีเมลอยู่แล้ว คุณมีผู้ใช้ที่ไม่มีที่อยู่อีเมลแล้ว

เอกสารที่เกี่ยวข้องสำหรับเรื่องนี้:

หากเอกสารไม่มีค่าสำหรับเขตข้อมูลที่จัดทำดัชนีไว้ในดัชนีที่ไม่ซ้ำกันดัชนีจะจัดเก็บค่า Null สำหรับเอกสารนี้ เนื่องจากข้อ จำกัด ที่ไม่ซ้ำกัน MongoDB จะอนุญาตเฉพาะเอกสารหนึ่งฉบับที่ขาดเขตข้อมูลที่จัดทำดัชนี หากมีมากกว่าหนึ่งเอกสารที่ไม่มีค่าสำหรับเขตข้อมูลที่จัดทำดัชนีหรือไม่มีเขตข้อมูลที่จัดทำดัชนีการสร้างดัชนีจะล้มเหลวด้วยข้อผิดพลาดคีย์ที่ซ้ำกัน

คุณสามารถรวมข้อ จำกัด ที่ไม่ซ้ำกับดัชนีกระจัดกระจายเพื่อกรองค่า null เหล่านี้จากดัชนีเฉพาะและหลีกเลี่ยงข้อผิดพลาด

ดัชนีที่ไม่ซ้ำกัน

ดัชนีกระจัดกระจายมีเฉพาะรายการสำหรับเอกสารที่มีเขตข้อมูลที่จัดทำดัชนีแม้ว่าเขตข้อมูลดัชนีประกอบด้วยค่า Null

กล่าวอีกนัยหนึ่งดัชนีกระจัดกระจายก็โอเคกับเอกสารหลายฉบับที่มีnullค่าทั้งหมด

ดัชนีกระจัดกระจาย


จากความคิดเห็น:

ข้อผิดพลาดของคุณบอกว่ามีการตั้งชื่อคีย์mydb.users.$email_1ซึ่งทำให้ฉันสงสัยว่าคุณมีดัชนีทั้งสองusers.emailและusers.local.email(อดีตเก่าและไม่ได้ใช้ในขณะนี้) การลบฟิลด์ออกจากโมเดล Mongoose จะไม่ส่งผลกระทบต่อฐานข้อมูล ตรวจสอบกับmydb.users.getIndexes()กรณีนี้และลบดัชนีที่ไม่ต้องการด้วยmydb.users.dropIndex(<name>)ตนเอง


1
ฉันเพิ่งลบเอกสารที่ว่างและมันทำงาน :) +1 .. ขอบคุณสำหรับความช่วยเหลือ
Trialcoder

70
ข้อผิดพลาดของคุณบอกว่ามีการตั้งชื่อคีย์mydb.users.$email_1ซึ่งทำให้ฉันสงสัยว่าคุณมีดัชนีทั้งสองusers.emailและusers.local.email(อดีตเก่าและไม่ได้ใช้ในขณะนี้) การลบฟิลด์ออกจากโมเดล Mongoose จะไม่ส่งผลกระทบต่อฐานข้อมูล ตรวจสอบกับmydb.users.getIndexes()กรณีนี้และลบดัชนีที่ไม่ต้องการด้วยmydb.users.dropIndex(<name>)ตนเอง
RickN

17
หรือใช้db.users.dropIndexes()หากคุณทำการเปลี่ยนแปลงดัชนีหลายรายการ
cs_stackX

1
นี่เป็นปัญหาสำหรับฉันเมื่อฉันใช้ปลั๊กอิน mongoose หนังสือเดินทาง - ท้องถิ่น - พังพอนโดยไม่ต้องตั้งชื่อผู้ใช้สำหรับผู้ใช้ใหม่
sshow

1
เป็นเรื่องหรือมุมมองหรือแม้กระทั่งความเห็น @titoih - เป็นโมฆะหรือไม่มีคุณค่าที่คุ้มค่าเหมือนกันหรือเป็นกรณีพิเศษหรือไม่? "a @ bc" และ "a @ bc" เหมือนกันคือ "ไม่มีอะไร" และ "ไม่มีอะไร" เหมือนกันหรือไม่? ด้วยดัชนีที่ไม่กระจายคำตอบคือ "ใช่" ใน MongoDB ฐานข้อมูลอื่น (เช่น MySQL) จะพูดว่า "ไม่"
RickN

65

หากคุณยังอยู่ในสภาพแวดล้อมการพัฒนาของคุณฉันจะลบฐานข้อมูลทั้งหมดและเริ่มต้นด้วยสคีมาใหม่ของคุณ

จากบรรทัดคำสั่ง

 mongo
use dbName;
db.dropDatabase();
exit

47
ฉันคิดว่าวิธีนี้จะก้าวร้าวมากฉันคิดว่าเพียงพอกับdb.collection.dropIndexes()ที่ cs_stackX พูด
JorgeGarza

2
@JorgeGarza ฉันมีปัญหาเดียวกัน ฉันทิ้งคอลเล็กชันและทุกอย่างก็เริ่มทำงานได้ดีหลังจากนั้น
Sandip Subedi

ฉันบังเอิญเริ่มต้นการเก็บด้วย Id ที่ไม่ซ้ำกันสำหรับสองสาขาของฉัน ต่อมาเมื่อฉันต้องการเพิ่มเอกสารหลายฉบับด้วยรหัสเดียวกันมันจะไม่ให้ฉันจนกว่าฉันจะลบคอลเลกชันและกลับมาใหม่
เมียร์ไนเดอร์

1
หากคุณยังใหม่กับการพัฒนาของคุณนี่เป็นโอกาสที่ดีในการทดสอบและหาวิธีแก้ปัญหานี้ ... แทนที่จะพบปัญหานี้เมื่อคุณมีข้อมูลผู้ใช้กิกะไบต์ที่จัดเก็บไว้แล้ว
Janac Meena

ความคิดเห็นของ @JorgeGarza สมเหตุสมผล ดัชนีที่ลดลงจะถูกสร้างใหม่อีกครั้งโดยไฟล์ Schema เมื่อเซิร์ฟเวอร์รีสตาร์ท นอกจากนี้ยังใช้งานได้
retr0

26

ตรวจสอบดัชนีการรวบรวม

ฉันมีปัญหานั้นเนื่องจากดัชนีที่ล้าสมัยในการรวบรวมสำหรับเขตข้อมูลซึ่งควรเก็บไว้โดยเส้นทางใหม่ที่แตกต่างกัน

พังพอนเพิ่มดัชนีเมื่อคุณระบุเขตข้อมูลที่ไม่ซ้ำกัน


21

โดยทั่วไปแล้วข้อผิดพลาดนี้จะบอกว่าคุณมีดัชนีที่ไม่ซ้ำกันในฟิลด์เฉพาะเช่น: "email_address" ดังนั้น mongodb จึงคาดว่าค่าที่อยู่อีเมลที่ไม่ซ้ำกันสำหรับแต่ละเอกสารในคอลเลกชัน

ดังนั้นสมมติว่าก่อนหน้านี้ในสคีมาของคุณไม่มีการกำหนดดัชนีที่ไม่ซ้ำกันและจากนั้นคุณลงชื่อสมัครใช้ 2 คนด้วยที่อยู่อีเมลเดียวกันหรือไม่มีที่อยู่อีเมล (ค่า null)

ต่อมาคุณเห็นว่ามีข้อผิดพลาด ดังนั้นคุณจึงพยายามแก้ไขโดยเพิ่มดัชนีเฉพาะลงในสคีมา แต่คอลเลกชันของคุณมีรายการซ้ำดังนั้นข้อความแสดงข้อผิดพลาดแจ้งว่าคุณไม่สามารถแทรกค่าซ้ำกันได้อีก

คุณมีสามตัวเลือกเป็นหลัก:

  1. วางคอลเลกชัน

    db.users.drop();

  2. ค้นหาเอกสารที่มีค่านั้นและลบทิ้ง สมมติว่าค่านั้นเป็นโมฆะคุณสามารถลบได้โดยใช้:

    db.users.remove({ email_address: null });

  3. วางดัชนีที่ไม่ซ้ำกัน:

    db.users.dropIndex(indexName)

ฉันหวังว่านี่จะช่วยได้ :)


18

ฉันต้องการอธิบายคำตอบ / วิธีแก้ปัญหาเช่นนี้ฉันอธิบายให้ 5 ปีเพื่อให้ทุกคนสามารถเข้าใจ

ฉันมีแอพฉันต้องการให้คนลงทะเบียนด้วยอีเมลรหัสผ่านและหมายเลขโทรศัพท์ ในฐานข้อมูล MongoDB ของฉันฉันต้องการระบุคนที่ไม่ซ้ำกันตามหมายเลขโทรศัพท์และอีเมลของพวกเขา - ดังนั้นนี่หมายความว่าทั้งหมายเลขโทรศัพท์และอีเมลจะต้องไม่ซ้ำกันสำหรับทุกคน

อย่างไรก็ตามมีปัญหา: ฉันรู้ว่าทุกคนมีเครื่องโทรศัพท์ แต่ไม่ใช่ทุกคนที่มีที่อยู่อีเมล

ผู้ที่ไม่มีที่อยู่อีเมลได้ให้สัญญากับฉันว่าพวกเขาจะมีที่อยู่อีเมลภายในสัปดาห์หน้า แต่ฉันต้องการให้พวกเขาลงทะเบียนต่อไป - ดังนั้นฉันบอกพวกเขาให้ลงทะเบียนเครื่องเสียงของพวกเขาเมื่อพวกเขาปล่อยให้ช่องป้อนข้อมูลอีเมลว่างเปล่า

พวกเขาทำเช่นนั้น

ฐานข้อมูลของฉันต้องมีที่อยู่อีเมลที่ไม่ซ้ำกัน - แต่ฉันมีผู้คนจำนวนมากที่มี 'null' เป็นที่อยู่อีเมลของพวกเขา ดังนั้นฉันไปที่รหัสของฉันและบอก schema ฐานข้อมูลของฉันเพื่ออนุญาตฟิลด์ที่อยู่อีเมลว่าง / ว่างซึ่งในภายหลังฉันจะกรอกด้วยที่อยู่อีเมลที่ไม่ซ้ำกันเมื่อผู้ที่สัญญาว่าจะเพิ่มอีเมลของพวกเขาในโปรไฟล์ในสัปดาห์หน้า

ดังนั้นตอนนี้มันเป็น win-win สำหรับทุกคน (แต่คุณ; -]): ผู้คนลงทะเบียนฉันมีความสุขที่ได้รับข้อมูล ... และฐานข้อมูลของฉันมีความสุขเพราะมันถูกใช้อย่างดี ... แต่คุณล่ะ? ฉันยังไม่ได้ให้รหัสที่ทำคี

นี่คือรหัส: หมายเหตุ: คุณสมบัติกระจัดกระจายในอีเมลเป็นสิ่งที่บอกฐานข้อมูลของฉันเพื่อให้ค่า null ซึ่งจะเต็มไปด้วยค่าที่ไม่ซ้ำในภายหลัง

var userSchema = new mongoose.Schema({
  local: {
    name: { type: String },
    email : { type: String, require: true, index:true, unique:true,sparse:true},
    password: { type: String, require:true },
  },
  facebook: {
    id           : { type: String },
    token        : { type: String },
    email        : { type: String },
    name         : { type: String }
  }
});

var User = mongoose.model('User',userSchema);

module.exports = User;

ฉันหวังว่าฉันจะอธิบายมันอย่างดี Happy NodeJS การเข้ารหัส / การแฮ็ก!


หากคุณต้องการsparseดัชนีและuniqueการตรวจสอบและมีเขตข้อมูลอื่นที่ไม่จำเป็นคุณจะต้องใช้partialFilterExpressionตัวเลือก ดูคำตอบนี้stackoverflow.com/a/34600171/728287
Gianfranco P.


4

ในสถานการณ์นี้เข้าสู่ Mongo เพื่อค้นหาดัชนีที่คุณไม่ได้ใช้อีกต่อไป (ในกรณีของอีเมล 'OP') จากนั้นเลือกดร็อปดัชนี ป้อนคำอธิบายรูปภาพที่นี่


3

นี่คือประสบการณ์ที่ฉันชื่นชอบ:

ในสคีมา 'ผู้ใช้' ฉันตั้ง 'ชื่อ' เป็นคีย์ที่ไม่ซ้ำกันจากนั้นเรียกใช้การดำเนินการบางอย่างซึ่งฉันคิดว่าได้ตั้งค่าโครงสร้างฐานข้อมูลแล้ว

จากนั้นฉันเปลี่ยนรหัสเฉพาะเป็น 'ชื่อผู้ใช้' และไม่ผ่านค่า 'ชื่อ' อีกต่อไปเมื่อฉันบันทึกข้อมูลลงในฐานข้อมูล ดังนั้น mongodb อาจตั้งค่า 'ชื่อ' ของบันทึกใหม่โดยอัตโนมัติเป็นโมฆะซึ่งเป็นคีย์ที่ซ้ำกัน ฉันลองใช้คีย์ 'name' เป็นคีย์ที่ไม่ซ้ำกัน {name: {unique: false, type: String}}ในสคีมา 'ผู้ใช้' เพื่อแทนที่การตั้งค่าดั้งเดิม อย่างไรก็ตามมันใช้งานไม่ได้

ในที่สุดฉันได้แก้ปัญหาของตัวเอง:

เพียงตั้งค่าคีย์สุ่มที่ไม่น่าจะซ้ำกับคีย์ 'ชื่อ' เมื่อคุณบันทึกข้อมูลของคุณ วิธีการทางคณิตศาสตร์'' + Math.random() + Math.random() ทำให้สตริงแบบสุ่ม


12
ฉันไม่คิดว่านี่เป็นวิธีแก้ปัญหาที่ถูกต้อง แต่เพียงคุณปิดบังปัญหา
Rick

น่าเกลียด แต่ในทางปฏิบัติ
แอนโทนี่

3

ฉันมีปัญหาเดียวกัน การลองแก้ไขจุดบกพร่องในรูปแบบต่างๆไม่สามารถเข้าใจได้ ฉันลองวางคอลเล็กชันและทำงานได้ดีหลังจากนั้น แม้ว่านี่จะไม่ใช่วิธีที่ดีหากคอลเลกชันของคุณมีเอกสารจำนวนมาก แต่ถ้าคุณอยู่ในสถานะเริ่มต้นของการพัฒนาให้ลองทิ้งคอลเล็กชัน

db.users.drop();

2

นี่เป็นเพราะมีคอลเลกชันที่มีชื่อเดียวกันกับการกำหนดค่า .. เพียงลบคอลเลกชันออกจาก mongodb ของคุณผ่าน mongo shell แล้วลองอีกครั้ง

db.collectionName.remove ()

ตอนนี้เรียกใช้แอปพลิเคชันของคุณซึ่งควรจะใช้งานได้


2

ฉันมีปัญหาที่คล้ายกันและฉันตระหนักว่าโดยค่าเริ่มต้น Mongo สนับสนุนหนึ่ง schema ต่อคอลเลกชันเท่านั้น จัดเก็บสคีมาใหม่ของคุณในคอลเล็กชันอื่นหรือลบเอกสารที่มีอยู่ด้วยสคีมาที่เข้ากันไม่ได้ภายในคอลเลกชันปัจจุบันของคุณ หรือหาวิธีที่จะมีสคีมามากกว่าหนึ่งคอลเลกชัน


2

ฉันยังประสบปัญหานี้และฉันแก้ไขมัน ข้อผิดพลาดนี้แสดงว่ามีอีเมลอยู่ที่นี่แล้ว ดังนั้นคุณเพียงแค่ลบบรรทัดนี้ออกจากรุ่นของคุณสำหรับแอตทริบิวต์อีเมล

unique: true

อาจเป็นไปได้ว่าแม้ว่ามันจะไม่ทำงาน ดังนั้นเพียงแค่ต้องลบการเก็บรวบรวมจาก MongoDB ของคุณและรีสตาร์ทเซิร์ฟเวอร์ของคุณ


1

ฉันได้รับปัญหาเดียวกันนี้เมื่อฉันมีการกำหนดค่าต่อไปนี้ใน config / models.js ของฉัน

module.exports.models = {
  connection: 'mongodb',
  migrate: 'alter'
}

การเปลี่ยนย้ายจาก 'แก้ไข' เป็น 'ปลอดภัย' แก้ไขให้ฉัน

module.exports.models = {
  connection: 'mongodb',
  migrate: 'safe'
}

1

ปัญหาเดียวกันหลังจากลบคุณสมบัติจากสคีมาหลังจากสร้างดัชนีในการบันทึกครั้งแรก การลบคุณสมบัติออกจากสคีมานำไปสู่ค่า Null สำหรับคุณสมบัติที่ไม่มีอยู่ซึ่งยังคงมีดัชนีอยู่ วางดัชนีหรือเริ่มต้นด้วยคอลเลกชันใหม่จากศูนย์ช่วย

หมายเหตุ: ข้อความแสดงข้อผิดพลาดจะนำคุณไปสู่กรณีนั้น มันมีเส้นทางที่ไม่มีอยู่อีกต่อไป ฉันกรณีของฉันเส้นทางเก่าคือ ... $ uuid_1 (นี่คือดัชนี!) แต่เส้นทางใหม่คือ .... * priv.uuid_1


1

ฉันมีปัญหาเดียวกันเมื่อฉันพยายามแก้ไข schema ที่กำหนดโดยใช้ mangoose ฉันคิดว่าปัญหานี้เกิดจากเหตุผลที่มีกระบวนการพื้นฐานบางอย่างเกิดขึ้นเมื่อสร้างคอลเลกชันเช่นอธิบายดัชนีที่ถูกซ่อนจากผู้ใช้ (อย่างน้อยในกรณีของฉัน) ดังนั้นทางออกที่ดีที่สุดที่ฉันพบคือการทิ้งคอลเล็กชันทั้งหมด และเริ่มใหม่อีกครั้ง


0

ฉันมีปัญหาเดียวกัน ปัญหาคือฉันลบฟิลด์หนึ่งจากโมเดล เมื่อฉันลบฐานข้อมูลมันจะแก้ไข



-3

เปลี่ยนชื่อคอลเล็กชันหากมีอยู่แล้วในฐานข้อมูลจะแสดงข้อผิดพลาด และถ้าคุณได้รับคุณสมบัติใด ๆ ที่ไม่ซ้ำกันข้อผิดพลาดเดียวกันจะเกิดขึ้น


-4

มีปัญหาเดียวกันฉันแก้ไขได้โดยลบuniqueแอตทริบิวต์ในสถานที่

เพียงค้นหาวิธีอื่นในการตรวจสอบหรือตรวจสอบค่าคุณสมบัติที่ไม่ซ้ำกันสำหรับสคีมาของคุณ


คุณควรให้ตัวอย่างกับโซลูชันของคุณ
Josh Adams

ก่อนอื่นให้ล้างการรวบรวมและ / หรือลบการรวบรวมทั้งหมดออกจากฐานข้อมูล Mongo ทำงานมันเป็นวิธีการแก้ปัญหาชั่วคราว การสร้างบันทึกอื่นด้วยค่าที่คล้ายกันแม้ว่าพวกเขาจะมีรหัสที่แตกต่างกันยังคงให้ข้อผิดพลาดที่สำคัญ E11000 ซ้ำกัน ฉันต้องการอนุญาตให้มีค่าซ้ำกันสำหรับคุณสมบัตินั้นดังนั้นฉันจึงลบคุณลักษณะเฉพาะออก
davyCode

-7

โปรดล้างการรวบรวมหรือลบการรวบรวมทั้งหมดจากฐานข้อมูล MongoDB แล้วลองอีกครั้งในภายหลัง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.