E11000 chỉ số lỗi trùng lặp khóa trong mongodb mongoose


228

Sau đây là userlược đồ của tôi trong user.jsmô hình -

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;

Đây là cách tôi đang sử dụng nó trong bộ điều khiển của mình -

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

Đây là cách tôi lưu nó trong 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"});
    }
});

Lỗi -

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

Tôi đã kiểm tra bộ sưu tập db và không có mục trùng lặp như vậy tồn tại, cho tôi biết những gì tôi đang làm sai?

FYI - req.body.emailreq.body.passwordđang tìm nạp các giá trị.

Tôi cũng đã kiểm tra bài đăng này nhưng không có trợ giúp STACK LINK

Nếu tôi xóa hoàn toàn thì nó sẽ chèn tài liệu, nếu không, nó sẽ báo lỗi "Sao y" ngay cả khi tôi có một mục trong local.email


1
Có lỗi tương tự! Trong quá trình phát triển, chúng tôi đã vô hiệu hóa lập chỉ mục tự động và đang sử dụng các tên / khóa lược đồ chữ thường. Sau đó, chúng tôi đã quyết định sử dụng TitleCase nhưng không cập nhật tên chỉ mục của chúng tôi (ví dụ: titleCase thay vì TitleCase). Vì vậy, khi chúng tôi kích hoạt lập chỉ mục, chúng tôi đã gặp lỗi này. Mất một lúc để tìm ra nó. Bạn sẽ muốn đảm bảo tất cả tên / khóa được đặt tên chính xác ở mọi nơi.
Jeach

6
Tôi đã có cùng một lỗi và thiết lập mô hình mongoose unique: falsekhông có bất kỳ tác động nào. Tôi nhận ra rằng trước tiên tôi phải bỏ cái bàn xuống và rồi nó sẽ hoạt động. Bạn có thể làm seomthing như db.whateverthecollection.drop({}). Hãy cẩn thận, nó xóa bộ sưu tập.
Pere

1
_id: mongoose.Types.ObjectId thêm vì id duy nhất là bắt buộc
Mayank Pandav

Câu trả lời:


239

Thông báo lỗi nói rằng đã có một bản ghi với nullemail. Nói cách khác, bạn đã có một người dùng không có địa chỉ email.

Các tài liệu liên quan cho việc này:

Nếu một tài liệu không có giá trị cho trường được lập chỉ mục trong một chỉ mục duy nhất, chỉ mục sẽ lưu trữ giá trị null cho tài liệu này. Do ràng buộc duy nhất, MongoDB sẽ chỉ cho phép một tài liệu thiếu trường được lập chỉ mục. Nếu có nhiều hơn một tài liệu không có giá trị cho trường được lập chỉ mục hoặc thiếu trường được lập chỉ mục, việc xây dựng chỉ mục sẽ thất bại với lỗi khóa trùng lặp.

Bạn có thể kết hợp ràng buộc duy nhất với chỉ mục thưa thớt để lọc các giá trị null này từ chỉ mục duy nhất và tránh lỗi.

chỉ số duy nhất

Các chỉ mục thưa thớt chỉ chứa các mục nhập cho các tài liệu có trường được lập chỉ mục, ngay cả khi trường chỉ mục chứa giá trị null.

Nói cách khác, một chỉ mục thưa thớt là ổn với nhiều tài liệu đều có nullgiá trị.

chỉ số thưa thớt


Từ ý kiến:

Lỗi của bạn nói rằng khóa được đặt tên mydb.users.$email_1khiến tôi nghi ngờ rằng bạn có một chỉ mục trên cả hai users.emailusers.local.email(Trước đây là cũ và không được sử dụng tại thời điểm này). Xóa một trường khỏi mô hình Mongoose không ảnh hưởng đến cơ sở dữ liệu. Kiểm tra mydb.users.getIndexes()xem đây có phải là trường hợp không và xóa thủ công chỉ mục không mong muốn bằng mydb.users.dropIndex(<name>).


1
Tôi vừa xóa tài liệu null đó và nó đã hoạt động :) +1 ..thx để được trợ giúp
Trialcoder

70
Lỗi của bạn nói rằng khóa được đặt tên mydb.users.$email_1khiến tôi nghi ngờ rằng bạn có một chỉ mục trên cả hai users.emailusers.local.email(Trước đây là cũ và không được sử dụng tại thời điểm này). Xóa một trường khỏi mô hình Mongoose không ảnh hưởng đến cơ sở dữ liệu. Kiểm tra mydb.users.getIndexes()xem đây có phải là trường hợp không và xóa thủ công chỉ mục không mong muốn bằng mydb.users.dropIndex(<name>).
RickN

17
Hoặc sử dụng db.users.dropIndexes()nếu bạn đang thực hiện nhiều thay đổi chỉ mục
cs_stackX

1
Đây là một vấn đề đối với tôi khi tôi đang sử dụng plugin mongoose-local-mongoose mà không đặt tên người dùng cho người dùng mới.
sshow

1
Đó là một vấn đề hoặc quan điểm hoặc thậm chí có thể là ý kiến, @titoih - là vô giá trị hoặc sự vắng mặt của một giá trị giống như bất kỳ giá trị nào khác hoặc đó là một trường hợp đặc biệt? "A @ bc" và "a @ bc" giống nhau, "không có gì" và "không có gì" giống nhau? Với một chỉ mục không thưa thớt, câu trả lời là "có" trong MongoDB. Các cơ sở dữ liệu khác (như MySQL) sẽ nói "không".
RickN

65

Nếu bạn vẫn ở trong môi trường phát triển của mình, tôi sẽ bỏ toàn bộ db và bắt đầu lại với lược đồ mới của bạn.

Từ dòng lệnh

 mongo
use dbName;
db.dropDatabase();
exit

47
Tôi nghĩ rằng giải pháp này rất tích cực, tôi nghĩ là đủ với db.collection.dropIndexes()như cs_stackX đã nói
JorgeGarza

2
@JorgeGarza Tôi cũng có vấn đề tương tự. Tôi vừa bỏ bộ sưu tập và mọi thứ bắt đầu hoạt động tốt sau đó.
Sandip Subedi

Tôi đã vô tình khởi tạo bộ sưu tập với một Id duy nhất cho hai lĩnh vực của mình. Sau này khi tôi muốn thêm nhiều tài liệu với cùng một Id Nó sẽ không cho phép tôi cho đến khi tôi xóa bộ sưu tập và xử lý lại.
Meir Snyder

1
Nếu bạn là người mới trong sự phát triển của mình, đây là cơ hội tốt để thử nghiệm và tìm ra cách giải quyết vấn đề này ... thay vì gặp phải vấn đề này khi bạn đã lưu trữ hàng gigabyte dữ liệu người dùng
Janac Meena

Nhận xét của @JorgeGarza có ý nghĩa. Các chỉ mục bị hủy sẽ được xây dựng lại một lần nữa bởi tệp Schema khi máy chủ được khởi động lại. Ngoài ra, nó đã làm việc.
lấy lại

26

Kiểm tra các chỉ số thu thập.

Tôi gặp vấn đề đó do các chỉ mục lỗi thời trong bộ sưu tập cho các trường, nên được lưu trữ bằng đường dẫn mới khác nhau.

Mongoose thêm chỉ mục, khi bạn chỉ định trường là duy nhất.


21

Về cơ bản, lỗi này có nghĩa là bạn đã có một chỉ mục duy nhất trên một trường cụ thể, ví dụ: "email_address", vì vậy mongodb mong đợi giá trị địa chỉ email duy nhất cho mỗi tài liệu trong bộ sưu tập.

Vì vậy, giả sử, trước đó trong lược đồ của bạn, chỉ mục duy nhất không được xác định và sau đó bạn đã đăng ký 2 người dùng có cùng địa chỉ email hoặc không có địa chỉ email (giá trị null).

Sau đó, bạn thấy rằng có một sai lầm. vì vậy bạn cố gắng sửa nó bằng cách thêm một chỉ mục duy nhất vào lược đồ. Nhưng bộ sưu tập của bạn đã có các bản sao, vì vậy thông báo lỗi nói rằng bạn không thể chèn lại một giá trị trùng lặp.

Về cơ bản, bạn có ba tùy chọn:

  1. Thả bộ sưu tập

    db.users.drop();

  2. Tìm tài liệu có giá trị đó và xóa nó. Giả sử giá trị là null, bạn có thể xóa nó bằng cách sử dụng:

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

  3. Bỏ chỉ mục duy nhất:

    db.users.dropIndex(indexName)

Tôi hy vọng điều này đã giúp :)


18

Tôi muốn giải thích câu trả lời / giải pháp cho vấn đề này giống như tôi đang giải thích cho một đứa trẻ 5 tuổi, để mọi người có thể hiểu.

Tôi có một ứng dụng. Tôi muốn mọi người đăng ký với email, mật khẩu và số điện thoại của họ. Trong cơ sở dữ liệu MongoDB của tôi, tôi muốn xác định mọi người duy nhất dựa trên cả số điện thoại và email của họ - vì vậy điều này có nghĩa là cả số điện thoại và email phải là duy nhất cho mỗi người.

Tuy nhiên, có một vấn đề: tôi đã nhận ra rằng mọi người đều có số điện thoại nhưng không phải ai cũng có địa chỉ email.

Những người không có địa chỉ email đã hứa với tôi rằng họ sẽ có địa chỉ email vào tuần tới. Nhưng dù sao tôi cũng muốn họ đăng ký - vì vậy tôi bảo họ tiếp tục đăng ký điện thoại của họ khi họ để trống trường nhập liệu email.

Họ làm như vậy.

Cơ sở dữ liệu của tôi CẦN một trường địa chỉ email duy nhất - nhưng tôi có rất nhiều người có 'null' là địa chỉ email của họ. Vì vậy, tôi đi đến mã của mình và nói với lược đồ cơ sở dữ liệu của mình để cho phép các trường địa chỉ email trống / null mà sau này tôi sẽ điền địa chỉ email duy nhất khi những người hứa sẽ thêm email vào hồ sơ của họ vào tuần tới.

Vì vậy, bây giờ nó là một chiến thắng cùng có lợi cho tất cả mọi người (nhưng bạn; -]): mọi người đăng ký, tôi rất vui khi có dữ liệu của họ ... và cơ sở dữ liệu của tôi rất vui vì nó đang được sử dụng độc đáo ... còn bạn thì sao? Tôi vẫn chưa cung cấp cho bạn mã đã tạo ra lược đồ.

Đây là mã: LƯU Ý: Thuộc tính thưa thớt trong email, là thông báo cho cơ sở dữ liệu của tôi cho phép các giá trị null mà sau này sẽ được điền với các giá trị duy nhất.

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;

Tôi hy vọng tôi đã giải thích nó độc đáo. Chúc mừng NodeJS mã hóa / hack!


nếu bạn muốn có một sparsechỉ mục và uniquexác nhận và có các trường khác không bắt buộc, bạn sẽ cần sử dụng partialFilterExpressiontùy chọn này. Xem câu trả lời này stackoverflow.com/a/34600171/728287
Gianfranco P.


4

Trong tình huống này, đăng nhập vào Mongo tìm chỉ mục mà bạn không sử dụng nữa (trong trường hợp 'email' của OP). Sau đó chọn Drop Index nhập mô tả hình ảnh ở đây


3

Đây là kinh nghiệm đáng tin cậy của tôi:

Trong lược đồ 'Người dùng', tôi đặt 'tên' là khóa duy nhất và sau đó chạy một số thực thi, mà tôi nghĩ rằng đã thiết lập cấu trúc cơ sở dữ liệu.

Sau đó, tôi đã thay đổi khóa duy nhất là 'tên người dùng' và không còn chuyển giá trị 'tên' khi tôi lưu dữ liệu vào cơ sở dữ liệu. Vì vậy, mongodb có thể tự động đặt giá trị 'tên' của bản ghi mới là null, đó là khóa trùng lặp. Tôi đã thử khóa 'tên' là không phải là khóa duy nhất {name: {unique: false, type: String}} trong lược đồ 'Người dùng' để ghi đè cài đặt gốc. Tuy nhiên, nó đã không hoạt động.

Cuối cùng, tôi đã thực hiện giải pháp của riêng mình:

Chỉ cần đặt một giá trị khóa ngẫu nhiên sẽ không có khả năng trùng lặp với khóa 'name' khi bạn lưu bản ghi dữ liệu của mình. Phương pháp Math đơn giản '' + Math.random() + Math.random() tạo ra một chuỗi ngẫu nhiên.


12
Tôi không nghĩ rằng đây là một giải pháp hợp lệ, bạn chỉ che giấu vấn đề.
Rick

Xấu xí nhưng thực dụng
Anthony

3

Tôi gặp vấn đề tương tự. Đã thử gỡ lỗi theo nhiều cách khác nhau không thể tìm ra. Tôi đã thử bỏ bộ sưu tập và nó hoạt động tốt sau đó. Mặc dù đây không phải là một giải pháp tốt nếu bộ sưu tập của bạn có nhiều tài liệu. Nhưng nếu bạn đang ở trạng thái phát triển ban đầu hãy thử bỏ bộ sưu tập.

db.users.drop();

2

Điều này là do đã có một bộ sưu tập có cùng tên với cấu hình..Chỉ cần xóa bộ sưu tập khỏi mongodb của bạn thông qua vỏ mongo và thử lại.

db.collectionName.remove ()

Bây giờ chạy ứng dụng của bạn, nó sẽ hoạt động


2

Tôi đã có một vấn đề tương tự và tôi nhận ra rằng mặc định mongo chỉ hỗ trợ một lược đồ cho mỗi bộ sưu tập. Lưu trữ lược đồ mới của bạn trong một bộ sưu tập khác hoặc xóa các tài liệu hiện có với lược đồ không tương thích trong bộ sưu tập hiện tại của bạn. Hoặc tìm một cách để có nhiều hơn một lược đồ cho mỗi bộ sưu tập.


2

Tôi cũng đã phải đối mặt với vấn đề này và tôi đã giải quyết nó. Lỗi này cho thấy email đã có mặt ở đây. Vì vậy, bạn chỉ cần xóa dòng này khỏi thuộc tính Model cho email.

unique: true

Điều này có thể là ngay cả khi nó không hoạt động. Vì vậy, chỉ cần xóa bộ sưu tập khỏi MongoDB của bạn và khởi động lại máy chủ của bạn.


1

Tôi gặp vấn đề tương tự khi tôi có cấu hình sau trong config / model.js

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

Thay đổi di chuyển từ 'thay đổi' thành 'an toàn' đã sửa nó cho tôi.

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

1

vấn đề tương tự sau khi loại bỏ các thuộc tính khỏi một lược đồ sau khi lần đầu tiên xây dựng một số chỉ mục về lưu. xóa thuộc tính khỏi lược đồ dẫn đến giá trị null cho thuộc tính không tồn tại, vẫn có chỉ mục. bỏ chỉ mục hoặc bắt đầu với một bộ sưu tập mới từ đầu giúp ở đây.

lưu ý: thông báo lỗi sẽ dẫn bạn trong trường hợp đó. nó có một con đường, nó không còn tồn tại nữa. Theo trường hợp của tôi, đường dẫn cũ là ... $ uuid_1 (đây là một chỉ mục!), nhưng đường dẫn mới là .... * private.uuid_1


1

Tôi gặp vấn đề tương tự khi tôi cố gắng sửa đổi lược đồ được xác định bằng xoài. Tôi nghĩ vấn đề này là do lý do có một số quy trình cơ bản được thực hiện khi tạo một bộ sưu tập như mô tả các chỉ số được ẩn khỏi người dùng (ít nhất là trong trường hợp của tôi). Vì vậy, giải pháp tốt nhất tôi tìm thấy là bỏ toàn bộ bộ sưu tập và bắt đầu lại.


0

Tôi đã có cùng một vấn đề. Vấn đề là tôi đã loại bỏ một trường khỏi mô hình. Khi tôi bỏ db, nó sửa


0

đối với các nhà phát triển trong tương lai, tôi khuyên bạn nên xóa chỉ mục trong INDEX TAB bằng la bàn ... điều này KHÔNG XÓA BẤT KY tài liệu nào trong bộ sưu tập của bạn Quản lý chỉ mục


-3

Thay đổi tên bộ sưu tập nếu nó đã tồn tại trong cơ sở dữ liệu, nó sẽ hiển thị một lỗi. Và nếu bạn đưa ra bất kỳ thuộc tính nào là duy nhất thì lỗi tương tự sẽ xảy ra.


-4

Có vấn đề tương tự tôi đã giải quyết nó bằng cách loại bỏ uniquethuộc tính trên tài sản.

Chỉ cần tìm một cách khác để xác nhận hoặc kiểm tra các giá trị thuộc tính duy nhất cho lược đồ của bạn.


Bạn nên cung cấp một ví dụ với giải pháp của bạn.
Josh Adams

Trước tiên, xóa bộ sưu tập và / hoặc xóa toàn bộ bộ sưu tập khỏi cơ sở dữ liệu mongo hoạt động, đó chỉ là một giải pháp tạm thời. Tạo một bản ghi khác có giá trị tương tự mặc dù chúng có id khác nhau vẫn gây ra lỗi khóa trùng lặp E11000. Tôi muốn cho phép các giá trị trùng lặp cho thuộc tính đó vì vậy tôi chỉ cần xóa thuộc tính duy nhất.
dillyCode

-7

Vui lòng xóa bộ sưu tập hoặc Xóa toàn bộ bộ sưu tập khỏi cơ sở dữ liệu MongoDB và thử lại sau.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.