Helpex - Trao đổi & giúp đỡ Đăng nhập
12

Tôi đang thực hiện mối quan hệ với nhiều người với mongoDb và mongoose.js, tôi biết rằng có nhiều lựa chọn, tình huống của tôi là:

Tôi có hai tài liệu, người dùng và dự án, một người dùng có thể có nhiều dự án và một dự án có thể có nhiều người dùng, vì vậy trong trường hợp của tôi, tôi có 4 lựa chọn:

1 - Một mảng id_user bên trong tài liệu dự án.

2 - Một mảng id_project bên trong tài liệu người dùng.

3 - Một mảng id_user bên trong tài liệu dự án && Một mảng id_project bên trong tài liệu người dùng.

4 - Một bảng thứ ba ánh xạ mối quan hệ người dùng và dự án (giống như một cơ sở dữ liệu quan hệ).

Tùy chọn 1 và 2 không khả dụng, bởi vì, hãy tưởng tượng trong tình huống của tùy chọn 1 nếu tôi muốn tìm tất cả các dự án từ người dùng, tôi sẽ phải tìm id người dùng này bên trong mọi mảng tài liệu dự án của người dùng (xem qua mảng này trong mọi dự án), đây chắc chắn không phải là một cách tiếp cận tốt.

Tùy chọn 3 là tốt nhưng tôi sẽ phải thực hiện một số loại giao dịch để đảm bảo rằng cả hai tài liệu sẽ được viết, nó không tệ lắm, vì cả hai tài liệu sẽ được đọc nhiều hơn so với văn bản

Tùy chọn 4 đơn giản hơn vì khi tôi thêm một người dùng vào một dự án, tôi chỉ cần thêm một tài liệu mới với cả hai id (tôi nghĩ đó là giải pháp tốt, vì tôi sẽ không cần quan tâm đến giao dịch, đó là một giải pháp tốt?)

Vì vậy, giải pháp tốt nhất là gì?

12 hữu ích 0 bình luận 7.9k xem chia sẻ
8

Ngược lại, giải pháp 1 và 2 là cách tốt nhất của bạn. Giải pháp 3 có thể được xem xét khi tần suất cập nhật / tạo là rất ít so với tần suất đọc của các dự án và người dùng vì mặc dù để cập nhật / tạo, cần phải có hai truy vấn, sự dễ đọc sẽ bù đắp cho điều đó.

Để lựa chọn giữa giải pháp 1 và 2, bạn cần xem xét các tần số đọc. Bạn sẽ cần các dự án của một người dùng hay sử dụng một dự án thường xuyên hơn và chọn theo điều đó. Nếu bạn cảm thấy cả hai có tần suất tương đối giống nhau, tốt hơn là giữ cho đối tượng người dùng càng ít nhóm càng tốt. Dù bạn chọn tùy chọn nào, hãy cân nhắc giữ một indexmảng lưu trữ _id(của các dự án hoặc người dùng).

Đối với người yêu cũ.

userSchema = new Schema(
            {//otherstuff
               project_ids: [{type: Schema.Types.ObjectId, ref: 'Project'}})
              ...
            }) 
userSchema.index({'project_ids':1})

hoặc là

projectSchema = new Schema(
            {//otherstuff
               user_ids: [{type: Schema.Types.ObjectId, ref: 'User'}})
              ...
            }) 
projectSchema.index({'user_ids':1})

Giữ một chỉ mục trên mảng _idsẽ cải thiện đáng kể tốc độ truy vấn của bạn ở phía mà bạn sợ sẽ có chi phí đáng kể.

Nhưng hãy giữ cái indexduy nhất nếu mối quan hệ này là một mối quan hệ quan trọng với rất nhiều truy vấn đang diễn ra. Nếu đây chỉ là một tính năng phụ của dự án của bạn, bạn cũng có thể withoutlập chỉ mục.

Nếu người dùng có thể làm nhiều việc và có nhiều mối quan hệ, bạn sẽ cần đối tượng người dùng đó liên tục trong suốt ứng dụng của mình, vì vậy nếu ứng dụng của bạn không phải là dự án cụ thể, tốt hơn là không đặt id dự án trong lược đồ người dùng . Nhưng vì chúng tôi chỉ đang đặt id, nên dù sao thì nó cũng không quá tốn kém. Không cần phải lo lắng về điều đó.

Chỉ mục Reg trên cả hai mảng: Tất nhiên là có. Nhưng khi bạn sử dụng giải pháp 3, bạn hoàn toàn không cần chỉ mục vì bạn sẽ không thực hiện truy vấn để lấy danh sách các dự án của một người dùng hoặc danh sách người dùng trong một dự án. Giải pháp 3 làm cho việc đọc rất dễ dàng nhưng viết hơi rườm rà. Nhưng như bạn đã đề cập rằng trường hợp sử dụng của bạn liên quan đến reading>>writinggiải pháp 3 nhưng luôn có nguy cơ không nhất quán dữ liệu mà bạn cần phải lưu ý.

Lập chỉ mục chỉ làm cho mọi thứ nhanh hơn. Xem qua các tài liệu và thực hiện một chút về googling. Không có gì lạ mắt. Truy vấn trên các mảng được lập chỉ mục hiệu quả hơn các mảng bình thường. Đối với người yêu cũ. Hãy để chúng tôi giả sử bạn sử dụng giải pháp 2. Lưu trữ id dự án trong trường project_ids.

Bạn có thể nhận được các dự án của người dùng một cách dễ dàng. Đây là thẳng về phía trước.

Nhưng để có được người dùng của dự án1. Bạn cần một truy vấn như thế này.

User.find({project_ids:project._id},function(err,docs){
     //here docs will be the list of the users of project1
})
//The above query might be slow if the user base is large. 
//But it can be improved vastly by indexing the project_ids field in the User schema.

Tương tự cho giải pháp 1. Mỗi dự án có trường user_ids, hãy giả sử chúng ta có một user1. Để nhận được các dự án của người dùng, chúng tôi thực hiện truy vấn sau

Project.find({user_ids:user1._id},function(err,docs){
      //here docs will be the projects of user1
      //But it can be improved vastly by indexing the user_ids field in the Project schema.

Nếu bạn đang cân nhắc về giải pháp 1 so với giải pháp 2, tôi đoán giải pháp 1 là tốt hơn. Có thể có trường hợp bạn cần người dùng mà không có dự án của anh ấy nhưng khả năng yêu cầu dự án không có người dùng là khá thấp. Nhưng nó phụ thuộc vào trường hợp sử dụng chính xác của bạn.

8 hữu ích 5 bình luận chia sẻ
2

Giải pháp 1 và 2 trông không tệ lắm! Nếu bạn lập chỉ mục mảng ObjectIds, bạn có thể truy cập trực tiếp vào những gì bạn muốn.

Giải pháp 3 cũng có vẻ tốt, nhưng 4, không thực sự, bạn cần nhiều truy vấn hơn, ngoại trừ khi bạn có nhiều thay đổi giữa mối quan hệ của dự án và người dùng, nhưng không phải chính chúng.

Tôi thích giải pháp 1 với chỉ mục trên mảng. Tôi đoán rất nhiều lần bạn cần lấy đối tượng dự án phụ thuộc vào người dùng hoặc trực tiếp bằng id, vì vậy .find()sẽ làm được tất cả những gì bạn muốn. Tôi nghĩ không tệ khi giữ cho lược đồ người dùng với thông tin tối thiểu, chúng trông giống như các đối tượng cô lập và bạn có thể cần chúng cho các mục đích khác.

2 hữu ích 4 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ mongodb mongoose nosql , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading