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

Tại sao Mongoose có cả lược đồ và mô hình?

CHỈNH SỬA: Mặc dù điều này đã hữu ích cho nhiều người, như đã đề cập trong các bình luận, nó trả lời "làm thế nào" chứ không phải tại sao. Rất may, lý do tại sao của câu hỏi cũng đã được trả lời ở nơi khác, với câu trả lời này cho câu hỏi khác. Điều này đã được liên kết trong các bình luận một thời gian nhưng tôi nhận thấy rằng nhiều người có thể không hiểu được điều đó khi đọc.

Thường thì cách dễ nhất để trả lời loại câu hỏi này là với một ví dụ. Trong trường hợp này, ai đó đã làm điều đó cho tôi :)

Hãy xem ở đây:

http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/

CHỈNH SỬA: Bài viết gốc (như đã đề cập trong các bình luận) dường như không còn tồn tại, vì vậy tôi đang sao chép nó bên dưới. Có khi nào nó quay lại không hay nó vừa mới chuyển đi, vui lòng cho tôi biết.

Nó cung cấp một mô tả chi tiết về việc sử dụng các lược đồ trong các mô hình trong mongoose và lý do tại sao bạn muốn làm điều đó, đồng thời cũng chỉ cho bạn cách đẩy các tác vụ thông qua mô hình trong khi lược đồ là tất cả về cấu trúc, v.v.

Bài đăng gốc:

Hãy bắt đầu với một ví dụ đơn giản về việc nhúng một lược đồ vào bên trong một mô hình.

var TaskSchema = new Schema({
    name: String,
    priority: Number
});
 
TaskSchema.virtual('nameandpriority')
    .get( function () {
        return this.name + '(' + this.priority + ')';
    });
 
TaskSchema.method('isHighPriority', function() {
    if(this.priority === 1) {
        return true;
    } else {
        return false;
    }
}); 
 
var ListSchema = new Schema({
    name: String,
    tasks: [TaskSchema]
});
 
mongoose.model('List', ListSchema);
 
var List = mongoose.model('List');
 
var sampleList = new List({name:'Sample List'});

Tôi đã tạo một TaskSchema mới đối tượng với thông tin cơ bản mà một nhiệm vụ có thể có. Thuộc tính ảo Mongoose được thiết lập để kết hợp tên và mức độ ưu tiên của Nhiệm vụ một cách thuận tiện. Tôi chỉ chỉ định một getter ở đây nhưng những setter ảo cũng được hỗ trợ.

Tôi cũng đã xác định một phương thức tác vụ đơn giản được gọi là isHighPriority để chứng minh cách các phương pháp hoạt động với thiết lập này.

Trong ListSchema định nghĩa, bạn sẽ nhận thấy cách các tác vụ của tasks khóa được định cấu hình để giữ một mảng TaskSchema các đối tượng. Tác vụ tasks khóa sẽ trở thành một phiên bản của DocumentArray cung cấp các phương pháp đặc biệt để xử lý các tài liệu Mongo được nhúng.

Hiện tại, tôi chỉ vượt qua ListSchema đối tượng vào mongoose.model và rời khỏi TaskSchema ngoài. Về mặt kỹ thuật, không cần thiết phải chuyển TaskSchema thành một mô hình chính thức vì chúng tôi sẽ không lưu nó vào bộ sưu tập của riêng nó. Sau đó, tôi sẽ chỉ cho bạn cách nó không gây hại gì nếu bạn làm vậy và nó có thể giúp tổ chức tất cả các mô hình của bạn theo cùng một cách, đặc biệt là khi chúng bắt đầu kéo dài nhiều tệp.

Với List thiết lập mô hình, hãy thêm một vài nhiệm vụ vào đó và lưu chúng vào Mongo.

var List = mongoose.model('List');
var sampleList = new List({name:'Sample List'});
 
sampleList.tasks.push(
    {name:'task one', priority:1}, 
    {name:'task two', priority:5}
);
 
sampleList.save(function(err) {
    if (err) {
        console.log('error adding new list');
        console.log(err);
    } else {
        console.log('new list successfully saved'); 
    }
});

Thuộc tính nhiệm vụ trên bản sao của List của chúng tôi model (sampleList ) hoạt động giống như một mảng JavaScript thông thường và chúng ta có thể thêm các tác vụ mới vào nó bằng cách sử dụng push. Điều quan trọng cần lưu ý là tasks được thêm vào dưới dạng các đối tượng JavaScript thông thường. Đó là một sự khác biệt nhỏ có thể không trực quan ngay lập tức.

Bạn có thể xác minh từ Mongo shell rằng danh sách và nhiệm vụ mới đã được lưu vào mongo.

db.lists.find()
{ "tasks" : [
    {
        "_id" : ObjectId("4dd1cbeed77909f507000002"),
        "priority" : 1,
        "name" : "task one"
    },
    {
        "_id" : ObjectId("4dd1cbeed77909f507000003"),
        "priority" : 5,
        "name" : "task two"
    }
], "_id" : ObjectId("4dd1cbeed77909f507000001"), "name" : "Sample List" }

Bây giờ chúng ta có thể sử dụng ObjectId để kéo lên Sample List và lặp lại các nhiệm vụ của nó.

List.findById('4dd1cbeed77909f507000001', function(err, list) {
    console.log(list.name + ' retrieved');
    list.tasks.forEach(function(task, index, array) {
        console.log(task.name);
        console.log(task.nameandpriority);
        console.log(task.isHighPriority());
    });
});

Nếu bạn chạy đoạn mã cuối cùng đó, bạn sẽ gặp lỗi thông báo rằng tài liệu được nhúng không có phương thức isHighPriority . Trong phiên bản Mongoose hiện tại, bạn không thể truy cập trực tiếp vào các phương thức trên lược đồ được nhúng. Có một vé mở để sửa nó và sau khi đặt câu hỏi cho Mongoose Google Group, manimal45 đã đăng một bài giải hữu ích để sử dụng ngay bây giờ.

List.findById('4dd1cbeed77909f507000001', function(err, list) {
    console.log(list.name + ' retrieved');
    list.tasks.forEach(function(task, index, array) {
        console.log(task.name);
        console.log(task.nameandpriority);
        console.log(task._schema.methods.isHighPriority.apply(task));
    });
});

Nếu bạn chạy mã đó, bạn sẽ thấy kết quả sau trên dòng lệnh.

Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false

Với suy nghĩ về công việc đó, hãy quay TaskSchema thành mô hình Mongoose.

mongoose.model('Task', TaskSchema);
 
var Task = mongoose.model('Task');
 
var ListSchema = new Schema({
    name: String,
    tasks: [Task.schema]
});
 
mongoose.model('List', ListSchema);
 
var List = mongoose.model('List');

TaskSchema định nghĩa giống như trước nên tôi bỏ nó ra. Sau khi nó được chuyển thành một mô hình, chúng tôi vẫn có thể truy cập vào đối tượng Schema cơ bản của nó bằng cách sử dụng ký hiệu dấu chấm.

Hãy tạo một danh sách mới và nhúng hai phiên bản mô hình Nhiệm vụ vào trong đó.

var demoList = new List({name:'Demo List'});
 
var taskThree = new Task({name:'task three', priority:10});
var taskFour = new Task({name:'task four', priority:11});
 
demoList.tasks.push(taskThree.toObject(), taskFour.toObject());
 
demoList.save(function(err) {
    if (err) {
        console.log('error adding new list');
        console.log(err);
    } else {
        console.log('new list successfully saved'); 
    }
});

Khi chúng tôi nhúng các phiên bản mô hình Nhiệm vụ vào Danh sách, chúng tôi đang gọi toObject trên chúng để chuyển đổi dữ liệu của chúng thành các đối tượng JavaScript thuần túy mà List.tasks DocumentArray đang mong đợi. Khi bạn lưu các phiên bản mô hình theo cách này, tài liệu nhúng của bạn sẽ chứa ObjectIds .

Ví dụ mã hoàn chỉnh có sẵn dưới dạng ý chính. Hy vọng rằng những giải pháp thay thế này sẽ giúp mọi thứ suôn sẻ hơn khi Mongoose tiếp tục phát triển. Tôi vẫn còn khá mới đối với Mongoose và MongoDB, vì vậy, vui lòng chia sẻ các giải pháp và mẹo tốt hơn trong phần nhận xét. Chúc bạn lập mô hình dữ liệu vui vẻ!



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB - Tạo cơ sở dữ liệu

  2. Kết nối với cơ sở dữ liệu MongoDB

  3. Mongo trường A lớn hơn trường B

  4. Cách tham gia vào hai bộ sưu tập bổ sung với các điều kiện

  5. Cách đơn giản để tạo mã với Mongoose và Node.js và Underscore?