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

Cách lưu trữ một bộ tài liệu có thứ tự trong MongoDB mà không cần sử dụng bộ sưu tập có giới hạn

Dựa trên yêu cầu của bạn, một trong những cách tiếp cận có thể là thiết kế lược đồ của bạn, theo cách mà mỗi tài liệu có khả năng để chứa nhiều tài liệu và bản thân nó hoạt động như một vùng chứa có giới hạn .

{
  "_id":Number,
  "doc":Array
}

Mỗi tài liệu trong bộ sưu tập sẽ hoạt động như một vùng chứa có giới hạn và các tài liệu sẽ được lưu trữ dưới dạng mảng trong doc đồng ruộng. doc trường là một mảng, sẽ duy trì thứ tự chèn. Bạn có thể giới hạn số lượng tài liệu ở n . Vì vậy, _id trường của mỗi tài liệu vùng chứa sẽ tăng dần theo n , cho biết số lượng tài liệu mà một tài liệu vùng chứa có thể chứa.

Bằng cách làm những điều này, bạn tránh thêm extra fields vào tài liệu, extra indices , unnecessary sorts .

Chèn bản ghi đầu tiên

tức là khi bộ sưu tập trống.

var record = {"name" : "first"};
db.col.insert({"_id":0,"doc":[record]});

Chèn các bản ghi tiếp theo

  • Xác định _id của tài liệu vùng chứa cuối cùng và number trong số các tài liệu mà nó lưu giữ.
  • Nếu số lượng tài liệu mà nó lưu giữ ít hơn n , sau đó cập nhật tài liệu thecontainer với tài liệu mới, khác tạo một containerdocument mới.

Giả sử rằng mỗi container document có thể giữ 5 tối đa là tài liệu và chúng tôi muốn chèn một tài liệu mới.

var record = {"name" : "newlyAdded"};

// using aggregation, get the _id of the last inserted container, and the 
// number of record it currently holds.
db.col.aggregate( [ {
    $group : {
        "_id" : null,
        "max" : {
            $max : "$_id"
        },
        "lastDocSize" : {
            $last : "$doc"
        }
    }
}, {
    $project : {
        "currentMaxId" : "$max",
        "capSize" : {
            $size : "$lastDocSize"
        },
        "_id" : 0
    }
// once obtained, check if you need to update the last container or 
// create a new container and insert the document in it.
} ]).forEach( function(check) {
    if (check.capSize < 5) {
        print("updating");
        // UPDATE
        db.col.update( {
            "_id" : check.currentMaxId
        }, {
            $push : {
                "doc" : record
            }
        });
    } else {
        print("inserting");
        //insert
        db.col.insert( {
            "_id" : check.currentMaxId + 5,
            "doc" : [ record ]
        });
    }
})

Lưu ý rằng tập hợp aggregation , chạy ở phía máy chủ và rất hiệu quả, cũng lưu ý rằng tập hợp aggregation sẽ trả lại cho bạn một tài liệu thay vì con trỏ trong các phiên bản previous to 2.6 . Vì vậy, bạn sẽ cần sửa đổi đoạn mã trên để chỉ chọn từ một tài liệu duy nhất thay vì lặp lại con trỏ.

Chèn một tài liệu mới vào giữa các tài liệu

Bây giờ, nếu bạn muốn chèn một tài liệu mới vào giữa các tài liệu 12 , chúng tôi biết rằng tài liệu sẽ nằm trong vùng chứa có _id=0 và phải được đặt ở second vị trí trong doc mảng của vùng chứa đó.

vì vậy, chúng tôi sử dụng $each$position toán tử để chèn vào các vị trí cụ thể.

var record = {"name" : "insertInMiddle"};

db.col.update(
{
    "_id" : 0
}, {
    $push : {
        "doc" : {
            $each : [record],
            $position : 1
        }
    }
}
);

Xử lý quá dòng

Bây giờ, chúng ta cần xử lý các tài liệu overflowing trong mỗi container , giả sử chúng tôi chèn một tài liệu mới vào giữa, trong vùng chứa có _id=0 . Nếu vùng chứa đã có 5 tài liệu, chúng ta cần move the last document to the next container và làm như vậy cho đến khi tất cả các thùng chứa tài liệu trong khả năng của chúng, cuối cùng nếu được yêu cầu, chúng tôi cần tạo một thùng chứa để chứa các tài liệu tràn.

Thao tác phức tạp này nên được thực hiện ở phía máy chủ . Để xử lý điều này, chúng ta có thể tạo một tập lệnh như tập lệnh dưới đây và register nó với mongodb.

db.system.js.save( {
    "_id" : "handleOverFlow",
    "value" : function handleOverFlow(id) {
        var currDocArr = db.col.find( {
            "_id" : id
        })[0].doc;
        print(currDocArr);
        var count = currDocArr.length;
        var nextColId = id + 5;
        // check if the collection size has exceeded
    if (count <= 5)
        return;
    else {
        // need to take the last doc and push it to the next capped 
    // container's array
    print("updating collection: " + id);
    var record = currDocArr.splice(currDocArr.length - 1, 1);
    // update the next collection
    db.col.update( {
        "_id" : nextColId
    }, {
        $push : {
            "doc" : {
                $each : record,
                $position : 0
            }
        }
    });
    // remove from original collection
    db.col.update( {
        "_id" : id
    }, {
        "doc" : currDocArr
    });
    // check overflow for the subsequent containers, recursively.
    handleOverFlow(nextColId);
}
}

Vì vậy, after every insertion in between , chúng ta có thể gọi function này bằng cách chuyển id vùng chứa, handleOverFlow(containerId) .

Tìm nạp tất cả các bản ghi theo thứ tự

Chỉ cần sử dụng $unwind toán tử trong aggregate pipeline .

db.col.aggregate([{$unwind:"$doc"},{$project:{"_id":0,"doc":1}}]);

Tài liệu Đặt hàng lại

Bạn có thể lưu trữ từng tài liệu trong một vùng chứa có giới hạn với trường "_id":

.."doc":[{"_id":0,","name":"xyz",...}..]..

Nắm giữ mảng "doc" của vùng chứa có giới hạn mà bạn muốn sắp xếp lại các mục.

var docArray = db.col.find({"_id":0})[0];

Cập nhật id của họ để sau khi sắp xếp, thứ tự của mặt hàng sẽ thay đổi.

Sắp xếp mảng dựa trên _id của chúng.

docArray.sort( function(a, b) {
    return a._id - b._id;
});

cập nhật lại vùng chứa có giới hạn, với mảng tài liệu mới.

Nhưng sau đó, tất cả mọi thứ đều tóm gọn lại cách tiếp cận nào là khả thi và phù hợp với yêu cầu của bạn nhất.

Trả lời câu hỏi của bạn:

Tài liệu dưới dạng Mảng.

sử dụng $each$position toán tử trong db.collection.update() hoạt động như được mô tả trong câu trả lời của tôi.

Đúng. Nó sẽ ảnh hưởng đến hiệu suất, trừ khi bộ sưu tập có rất ít dữ liệu.

Đúng. Với Bộ sưu tập có giới hạn, bạn có thể mất dữ liệu.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Cách khai báo tên bộ sưu tập và tên kiểu máy trong mongoose

  2. Cách thực thi tổng hợp trong mongodb trong khung công tác Laravel

  3. Cách kết nối với mongoDB Atlas bằng mongoose

  4. Mongo DB:Tìm giá trị mảng lồng nhau

  5. So sánh sự khác biệt mongo trên hai bộ sưu tập