2012-02-03 30 views

Trả lời

43

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

Hãy xem ở đây:

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

EDIT: Các bài gốc (như đã đề cập trong các ý kiến) dường như không còn tồn tại , vì vậy tôi đang tái tạo nó bên dưới. Nếu nó đã trở lại, hoặc nếu nó vừa di chuyển, xin vui lòng cho tôi biết.

Nó cung cấp một mô tả phong nha của việc sử dụng lược đồ trong mô hình trong cầy mangut và tại sao bạn sẽ muốn làm điều đó, và cũng có thể cho bạn thấy làm thế nào để thúc đẩy nhiệm vụ thông qua các mô hình trong khi schema là tất cả về cấu trúc, vv

Bài đăng gốc:

Hãy bắt đầu với một ví dụ đơn giản về nhúng 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 đối tượng TaskSchema mới với thông tin cơ bản mà tác vụ có thể có. Một Mongoose virtual attribute được thiết lập để thuận tiện kết hợp tên và mức độ ưu tiên của Tác vụ. Tôi chỉ xác định một getter ở đây nhưng các bộ cài đặt ảo cũng được hỗ trợ.

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

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

Hiện tại, tôi chỉ chuyển đối tượng ListSchema vào mongoose.model và rời khỏi TaskSchema. Về mặt kỹ thuật, không cần phải biến TaskSchema thành một mô hình chính thức vì chúng tôi sẽ không lưu nó trong bộ sưu tập của chính nó. Sau đó tôi sẽ cho bạn thấy nó không gây hại gì nếu bạn làm 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 mở rộng nhiều tệp.

Với thiết lập mô hình List, hãy thêm một vài tác 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'); 
    } 
}); 

Nhiệm vụ thuộc tính về trường hợp của mô hình List của chúng tôi (simpleList) hoạt động giống như một mảng JavaScript thường xuyên và chúng ta có thể thêm các công việc mới để nó sử dụng push. Điều quan trọng cần lưu ý là các tác vụ được thêm vào như các đối tượng JavaScript thông thường. Đó là một sự phân biệt tinh tế có thể không trực quan ngay lập tức.

Bạn có thể xác minh từ vỏ Mongo 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 tôi có thể sử dụng ObjectId để kéo lên Sample List và lặp lại thông qua các tác 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 bit cuối cùng của mã, bạn sẽ gặp lỗi khi nói 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 các lược đồ được nhúng. Có open ticket để sửa lỗi và sau khi đặt câu hỏi cho Nhóm Mongoose của Google, manimal45 đã đăng một công việc 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 ý nghĩ xung quanh, hãy biến TaskSchema thành mẫu 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'); 

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

Hãy tạo danh sách mới và nhúng hai cá thể mô hình Tác vụ bên 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'); 
    } 
}); 

Như chúng ta nhúng các trường hợp mô hình công tác vào Danh sách chúng tôi đang gọi điện thoại toObject vào chúng để chuyển đổi dữ liệu của họ vào đồng bằng JavaScript đối tượng mà các List.tasksDocumentArray được mong đợi. Khi bạn lưu các phiên bản mẫu theo cách này, tài liệu được nhúng của bạn sẽ chứa ObjectIds.

Ví dụ mã hoàn chỉnh là available as a gist. Hy vọng rằng những công việc xung quanh này giúp những điều tốt đẹp hơn khi Mongoose tiếp tục phát triển. Tôi vẫn còn khá mới với Mongoose và MongoDB vì vậy xin vui lòng chia sẻ các giải pháp và mẹo tốt hơn trong phần bình luận. Chúc mừng mô hình dữ liệu!

+1

Thường không nên gửi các liên kết trống như một câu trả lời cho các câu hỏi được đăng trong SO vì liên kết có thể ngừng hoạt động (như trong trường hợp này). Ít nhất là sao chép/quá khứ và trích dẫn các phần có liên quan của bài viết bạn liên kết đến. – Behrang

+0

thực hiện - nó vẫn còn trong bộ nhớ cache của Google, vì vậy tương đối đơn giản –

+1

Để ghi lại, vấn đề phương pháp tài liệu được nhúng đã được sửa: https://github.com/LearnBoost/mongoose/issues/249#ref-commit-e18077a – Dakota

31

Giản đồ là một đối tượng xác định cấu trúc của bất kỳ tài liệu nào sẽ được lưu trữ trong bộ sưu tập MongoDB của bạn; nó cho phép bạn xác định các loại và trình duyệt tính hợp lệ cho tất cả các mục dữ liệu của bạn.

Mô hình là một đối tượng giúp bạn dễ dàng truy cập bộ sưu tập có tên, cho phép bạn truy vấn bộ sưu tập và sử dụng Giản đồ để xác thực bất kỳ tài liệu nào bạn lưu vào bộ sưu tập đó. Nó được tạo ra bằng cách kết hợp một Schema, một Connection và một tên bộ sưu tập.

Nguyên phrased bởi Valeri Karpov, MongoDB Blog

2

Tôi không nghĩ rằng câu trả lời chấp nhận thực sự trả lời cho câu hỏi đó được đặt ra. Câu trả lời không giải thích được lý do tại sao Mongoose đã quyết định yêu cầu nhà phát triển cung cấp cả biến Giản đồ và Mô hình. Một ví dụ về một khuôn khổ mà họ đã loại bỏ sự cần thiết cho nhà phát triển để xác định lược đồ dữ liệu là django - nhà phát triển viết mô hình của họ trong tệp models.py và để nó trong khuôn khổ để quản lý lược đồ. Lý do đầu tiên mà nói đến tâm trí cho lý do tại sao họ làm điều này, cho kinh nghiệm của tôi với django, là dễ sử dụng. Có lẽ quan trọng hơn là nguyên tắc DRY (không lặp lại) - bạn không cần phải nhớ cập nhật lược đồ khi bạn thay đổi mô hình - django sẽ làm điều đó cho bạn! Rails cũng quản lý lược đồ dữ liệu cho bạn - nhà phát triển không chỉnh sửa trực tiếp lược đồ, nhưng thay đổi lược đồ bằng cách xác định di chuyển điều khiển giản đồ.

Một lý do tôi có thể hiểu rằng Mongoose sẽ tách lược đồ và mô hình là các trường hợp mà bạn muốn xây dựng mô hình từ hai lược đồ. Kịch bản như vậy có thể giới thiệu phức tạp hơn là quản lý giá trị - nếu bạn có hai lược đồ được quản lý bởi một mô hình, tại sao chúng không phải là một lược đồ?

Có lẽ câu hỏi ban đầu là một di tích của hệ thống cơ sở dữ liệu quan hệ truyền thống. Trong thế giới NoSQL/Mongo trên thế giới, có lẽ lược đồ là linh hoạt hơn một chút so với MySQL/PostgreSQL, và do đó việc thay đổi lược đồ là thực hành phổ biến hơn.

0

Nói cách đơn giản,

Một mô hình là một mô hình đối tượng dữ liệu, như bạn sẽ tìm thấy trong một thiết kế pattern.It MVC định nghĩa Cấu trúc những loại dữ liệu phải được lưu trữ trong một cơ sở dữ liệu và những gì loại mối quan hệ dữ liệu có.

Một schema giống như một database schema, định nghĩa về những gì sẽ được lưu trữ trong một cơ sở dữ liệu.

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