MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Tài liệu trùng lặp MongoDB ngay cả sau khi thêm khóa duy nhất

Xin chúc mừng, bạn dường như đã tìm thấy một lỗi. Điều này chỉ xảy ra với MongoDB 3.0.0 trong thử nghiệm của tôi, hoặc ít nhất là không có ở MongoDB 2.6.6. Lỗi hiện đã được ghi lại tại SERVER-17599

LƯU Ý :Không thực sự là một "vấn đề" nhưng được xác nhận "bởi thiết kế". Bỏ tùy chọn cho phiên bản 3.0.0. Tuy nhiên, vẫn được liệt kê trong tài liệu.

Vấn đề là chỉ mục không được tạo và lỗi khi bạn cố gắng tạo chỉ mục này trên một bộ sưu tập có các bản sao hiện có trên các trường "khóa ghép". Ở trên, việc tạo chỉ mục sẽ mang lại kết quả này trong shell:

{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "errmsg" : "exception: E11000 duplicate key error dup key: { : 15.0, : 1.0 }",
    "code" : 11000,
    "ok" : 0
}

Khi không có bản sao nào xuất hiện, bạn có thể tạo chỉ mục như hiện tại bạn đang thử và nó sẽ được tạo.

Vì vậy, để giải quyết vấn đề này, trước tiên hãy xóa các bản sao bằng quy trình như sau:

db.events.aggregate([
    { "$group": {
        "_id": { "uid": "$uid", "sid": "$sid" },
        "dups": { "$push": "$_id" },
        "count": { "$sum": 1 }
    }},
    { "$match": { "count": { "$gt": 1 } }}
]).forEach(function(doc) {
    doc.dups.shift();
    db.events.remove({ "_id": {"$in": doc.dups }});
});

db.events.createIndex({"uid":1 , "sid": 1},{unique:true})

Sau đó, các chèn tiếp có chứa dữ liệu trùng lặp sẽ không được chèn và lỗi thích hợp sẽ được ghi lại.

Lưu ý cuối cùng ở đây là "dropDups" không phải là một giải pháp rất thanh lịch để loại bỏ dữ liệu trùng lặp. Bạn thực sự muốn thứ gì đó có nhiều quyền kiểm soát hơn như đã trình bày ở trên.

Đối với phần thứ hai, thay vì sử dụng .insert() sử dụng .update() phương pháp. Nó có tùy chọn "nâng cấp"

$collection->update(
    array( "uid" => 1, "sid" => 1 ),
    array( '$set' => $someData ),
    array( 'upsert' => true )
);

Vì vậy, các tài liệu "tìm thấy" được "sửa đổi" và các tài liệu không tìm thấy được "chèn". Cũng xem $setOnInsert để chỉ tạo một số dữ liệu nhất định khi tài liệu thực sự được chèn chứ không phải khi được sửa đổi.

Đối với nỗ lực cụ thể của bạn, cú pháp chính xác của .update() là ba đối số. "truy vấn", "cập nhật" và "tùy chọn":

$collection->update(
    array( "uid" => 1, "sid" => 1 ),
    array(
        '$set' => array( "field" => "this" ),
        '$inc' => array( "counter" => 1 ),
        '$setOnInsert' => array( "newField" => "another" )
   ),
   array( "upsert" => true )
);

Không có thao tác cập nhật nào được phép "truy cập cùng một đường dẫn" như được sử dụng trong thao tác cập nhật khác trong phần tài liệu "cập nhật" đó.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Khung tổng hợp Mongodb | Nhóm trên nhiều giá trị?

  2. Nhập dữ liệu vào MongoDB từ tệp JSON bằng Java

  3. Tổng quan về mã hóa cấp trường phía máy khách trong MongoDB

  4. Java, MongoDB:Làm thế nào để cập nhật mọi đối tượng trong khi lặp lại một bộ sưu tập lớn?

  5. Làm thế nào để giải quyết vấn đề thiếu giao dịch trong MongoDB?