Xin tư vấn bố cục cơ sở dữ liệu trong MongoDB



  • Em có 1 cơ sở dữ liệu nơi lưu các thành viên và tin nhắn của mỗi người, e có 2 phương án lưu thế này:

    Cách 1:

    var usersSchema = mongoose.Schema({
       [user: {
         id: String
         name: String,
         avatar: String,
         work: String,
         tinnhan: {[
              idNguoigui: String,
              nameNguoigui: String,
              avatarNguoigui: String,
              workNguoigui: String,
              tinnhan: String
         ]}
       }]
    });
    

    Cách 2:

    var usersSchema = mongoose.Schema({
       [user: {
         id: String
         name: String,
         avatar: String,
         work: String,
         tinnhan: {[
              idNguoigui: String,
              tinnhan: String
         ]}
       }]
    });
    

    Cách thứ 1, thì mỗi lần truy vấn vào tin nhắn sẽ hiển thị đầy đủ thông tin bao gồm (id,name,avatar,work) của người gửi.

    Cách thứ 2 ta chỉ nhận được id(idNguoigui) của người gửi và phải dùng câu lênh truy vấn thông tin từ giá trị idNguoigui rồi mới có thể xem thông tin của người gửi đến.


    Với cách thứ 1 nhanh gọn, truy vấn 1 lần và có tất cả nhưng có vẻ ngốn tài nguyên cơ sở dữ liệu nếu như 1 người có hàng trăm tin nhắn và phải lưu 1 số thông tin cơ bản của tất cả người gửi.

    Với cách thứ 2 tránh được tình trạng ngốn tài nguyên vô ích nhưng phải truy vấn thêm lần nữa mới có được thông tin Người Gửi, đây là 1 tin nhắn thì ko sao nhưng nếu có 100 tin nhắn thì phải dùng vông lặp qua từng idNguoigui trong aray tinnhan và truy vấn từng ID 1 để lấy thông tin. Như vậy sẽ làm giảm hiệu xuất.

    Mọi người tư vấn giúp e nên chọn phương án nào ạ, nếu ai có hướng giải quyết tốt hơn thì tư vấn giúp e với nhé



  • @Anh-Anh-Tran222 2 đoạn schema của bạn y như nhau nên chả rõ pa2 của bạn thế nào.
    Thứ nhất, một document của mongo tối đa 16 megabytes nên bạn phải cẩn thận khi không giới hạn size của các field.
    Thứ hai, pa1 làm thế có quá nhiều thông tin bị lặp lại. PA 1 của bạn mỗi lần lấy tinnhan là lại lặp thông tin user gửi, cuối cùng thì chỉ có tinnhan là khác nhau thôi ( góp ý thêm là bạn cần thêm timestamp field). Và chỉ tồn tại 1 cuộc hội thoại chung giữa user_id1-user_id2 trên toàn bộ db. Vậy đây sẽ là khóa để lưu vào mongo.

    var userSchema = new Schema({
    	id: String, //  nên dùng _id 
    	name: String,
    	avatar: String,
    	work: String,
    	is_active:Boolean,
    	conversations:[{ type : ObjectId, ref: 'Conversation' }]
    });
    
    var conversationSchema = new Schema({
      users_in:[{ type : ObjectId, ref: 'User' }],
      messages : [{ type: ObjectId, ref: 'Message' }],
      created_at: Date,
      updated_at: { type: Date, default: Date.now },
    });
    
    var messageSchema = new Schema({
      in: { type : ObjectId, ref: 'Conversation' },
      from: { type : ObjectId, ref: 'User' },
      message: String, 
      time: {
        type:Date,
        default:Date.now,
      }
    });
    
    exports.UserSchema = mongoose.model('User', userSchema);
    exports.ConversationSchema = mongoose.model('Conversation',conversationSchema );
    exports.MessageSchema = mongoose.model('Message',messageSchema );
    

    Bên trên là một phần code mình copy từ một sản phẩm làm cho đối tác, là copy ra nên nó có thể khá rối. Ngoài ra thì khi thiết kế mình có tính đến lưu trữ trên Redis nên mình mới băm nhỏ thành cách Schema khác nhau, bạn nên cân nhắc khi tham khảo.



  • Cách thứ 2 bạn có thể dùng $in tối ưu hơn cho việc query thay vì mỗi id một câu query.
    Cách khác: Không rõ bài toán của bạn như thế nào nhưng mình gợi ý có thể dùng tinnhan làm đối tượng document, ví dụ:
    [{
    tinnhan: String,
    idnguoigui: String,
    idnguoinhan: String,
    ngaygui: Date
    }]
    Việc truy vấn theo người gửi, người nhận hoặc ngày gửi sẽ dễ dàng hơn.


Log in to reply