2011-10-30 42 views
5

Tôi đang sử dụng để mô hình Mongoose PersonTransaction bộ sưu tập, trong đó mỗi Transaction sẽ phải tham chiếu đến hai Person trường hợp khác nhau:Mongoose: Làm thế nào để mô hình hóa một mối quan hệ nghịch đảo/nghịch đảo?

var TransactionSchema = new Schema({ 
    , amount   : { type: Number, required: true } 
    , from   : { type: ObjectId, required: true } 
    , to    : { type: ObjectId, required: true } 
    , date   : Date 
}); 

var PersonSchema = new Schema({ 
    name   : { type: String, required: true } 
    , transactions : [ObjectId] 
}); 

Tôi muốn mỗi Person để có một bộ sưu tập của tất cả các s Transaction rằng họ là hoặc giá trị to hoặc from cho. Cho đến nay, đây là cách tốt nhất mà tôi có thể tìm ra cách thực hiện:

TransactionSchema.pre('save', function(next, done) { 
    var transaction = this; 

    Person.findById(this.to, function (err, person) { 
     person.transactions.push(transaction); 
     person.save(); 
    }); 

    Person.findById(this.from, function (err, person) { 
     person.transactions.push(transaction); 
     person.save(); 
    }); 

    next(); 
}); 

Điều này có vẻ quá mức. Có cách nào tốt hơn để làm điều đó, hoặc tôi đang cố gắng sử dụng MongoDB quá nhiều như một cơ sở dữ liệu quan hệ? Thay vì có một bộ sưu tập gồm Transaction s được liên kết với từng cá thể Person, tôi có nên truy vấn trực tiếp bộ sưu tập Translation không?

Cảm ơn bạn.

Trả lời

7

Bạn phải suy nghĩ nhiều hơn về các truy vấn bạn sẽ thực hiện trên cơ sở dữ liệu khi bạn thiết kế lược đồ MongoDB.

Cố gắng sao chép dữ liệu để có tốc độ và tham chiếu nó cho tính toàn vẹn. Điều đó nghĩa là gì?
Ví dụ: khi bạn thực hiện truy vấn cho một Giao dịch, tôi đoán bạn không cần tất cả chi tiết người dùng từ lần đầu tiên không? (Bạn cần email của người dùng, vị trí khi hiển thị thông tin về một giao dịch?)
Tôi nghĩ rằng bạn chỉ có thể cần id người dùng và tên người dùng, vì vậy bạn nên làm điều gì đó như thế này:

var TransactionSchema = new Schema({ 
    , amount   : { type: Number, required: true } 
    , from   : { 
    user_id: { 
     type: ObjectId 
    , required: true 
    } 
    , username: { 
     type: String 
    , required: true 
    } 
    } 
    , to    : { 
    user_id: { 
     type: ObjectId 
    , required: true 
    } 
    , username: { 
     type: String 
    , required: true 
    } 
    } 
    , date   : Date 
}); 

Vì vậy, thay vì làm 3 truy vấn cho trang hiển thị chi tiết giao dịch (một cho giao dịch và 2 truy vấn bổ sung cho tên người dùng), bạn sẽ chỉ có một.
Đây chỉ là một ví dụ, bạn có thể áp dụng cùng một logic cho lược đồ người dùng, tùy thuộc vào những gì bạn đang cố gắng đạt được.

Dù sao tôi không nghĩ rằng phần mềm trung gian của bạn là ok, vì bạn không kiểm tra lỗi ở đó (bạn luôn gọi điện thoại tiếp theo cho dù có gì). Đây là cách tôi sẽ viết các middleware (không kiểm tra, nhưng ý tưởng là quan trọng):

TransactionSchema.pre('save', function(next, done) { 
    var transaction = this; 

    Person.where('_id').in([this.to, this.from]).run(function (err, people) { 
    if (people.length != 2) { next(new Error("To or from doesn't exist")); return; } 
    Step(
     function save_to() { 
     people[0].transactions.push(transaction); 
     people[0].save(this); 
     }, 
     function save_from(err) { 
     if (err) { next(err); return; } 
     people[1].transactions.push(transaction); 
     people[1].save(this); 
     }, 
     function callback(err) { 
     next(err); 
     } 
    ); 
    }); 
}); 

Trong đoạn mã trên tôi đang sử dụng thư viện Step để kiểm soát dòng chảy và tôi chỉ sử dụng một truy vấn thay vì hai (khi tìm kiếm "đến" và "từ").

+0

nhiều điều! chỉ muốn tôi cần đọc –

+0

Làm tốt hơn để thực hiện việc này trước khi lưu hoặc lưu sau. Điều gì sẽ xảy ra nếu giao dịch không được lưu do lỗi xác thực hoặc bất kỳ lỗi nào khác. Bạn sẽ không chỉ cần thêm mục giả vào người? Nếu bạn làm điều này trong bài tiết kiệm bạn không bạn sẽ phải truy vấn cho giao dịch một lần nữa – raju

Các vấn đề liên quan