Hướng dẫn reference vs embedded mongodb - tham chiếu so với mongodb nhúng

1. Embedded Documents là gì?

Embedded documents (Tài liệu nhúng) là documents có lược đồ riêng và là 1 phần của documents khác. Hiểu đơn giản thì embedded documents là 1 field nằm trong 1 collection thay vì lưu dữ liệu kiểu References ta phải thiết kế 2 collection để thể hiện mối quan hệ One-to-Many.

Embedded documents có mọi đặc điểm như 1 model, ta có thể sử dụng validators, middleware,... để xử lý lỗi khi làm việc với kiểu dữ liệu này.

Trong Mongoose, Embedded documents được khai báo dưới dạng array trong collection chứa nó và như nói phía trên, nó sẽ có 1 lược đồ riêng nhưng nằm trong cùng 1 file với collection chính.

Ví dụ: Ta cần quản lý các Students và mỗi students sẽ có nhiều Projects khác nhau. Khi này ta sẽ có 1 file chứa lược đồ như sau: Ta cần quản lý các Students và mỗi students sẽ có nhiều Projects khác nhau. Khi này ta sẽ có 1 file chứa lược đồ như sau:

var Projects = new Schema({
  title: String,
  unit: String
})


var Student = new Schema({
  name: String,
  age: Number,
  projects: [Projects]
})

mongoose.model('Student', Student);

Ta có thể thấy cặp key-value projects: [Projects] trong lược đồ Student, value là 1 array đặc biệt có các phương thức cụ thể để làm việc với Embedded Documents và array này là một thể hiện của DocumentArray. Ở các cặp key-value khác thì value là 1 kiểu dữ liệu được định nghĩa sẵn. Ta cần định nghĩa cho DocumentArray này bằng 1 lược đồ riêng.projects: [Projects] trong lược đồ Student, value là 1 array đặc biệt có các phương thức cụ thể để làm việc với Embedded Documents và array này là một thể hiện của DocumentArray. Ở các cặp key-value khác thì value là 1 kiểu dữ liệu được định nghĩa sẵn. Ta cần định nghĩa cho DocumentArray này bằng 1 lược đồ riêng.

Lưu ý: Lược đồ con luôn phải được xác định trước lược đồ chính.: Lược đồ con luôn phải được xác định trước lược đồ chính.

2. So sánh Embedded Documents vs References

Trước khi so sánh giữa 2 kiểu mô hình dữ liệu thì ta xem qua với ví dụ phía trên khi sử dụng kiểu References thì xây dựng lược đồ như thế nào đã nhé.References thì xây dựng lược đồ như thế nào đã nhé.

Ta có 2 file: Project.js và Student.js

//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
//Student.js
var Student = new Schema({
  name: String,
  age: Number
});

mongoose.model('Student', Student);

References lưu trữ các mối quan hệ giữa dữ liệu bằng cách link từ collection này sang collection khác (tạo tham chiếu đến thằng cha) thông qua ObjectIds. Ở đây, nếu ta có một bản dữ liệu trong từng Student thì ta lưu ObjectID của Student trên từng Project. Thuộc tính ref phải khớp chính xác với tên model trong định nghĩa model của chúng ta.

Cơ bản thì cách sử dụng 2 mô hình dữ liệu này trong Mongoose là như vậy. Mỗi kiểu có ưu, nhược điểm khác nhau:

Embedded DocumentsReferences
Ưu điểm - Truy vấn và cập nhật dữ liệu dễ dàng.- Đạt hiệu suất cao trong việc đọc dữ liệu
- Đạt hiệu suất cao trong việc đọc dữ liệu
- Có thể cung cấp linh hoạt hơn với truy vấn. - Đạt hiệu suất cao trong việc ghi dữ liệu
- Đạt hiệu suất cao trong việc ghi dữ liệu
Nhược điểm - Kích thước document lớn ảnh hưởng đến việc ghi dữ liệu vì mỗi document không thể vượt quá 16MB - Với các hệ thống có nhiều collections thì truy vấn sẽ khó khăn hơn, yêu cầu nhiều công việc hơn

Bài viết này nói về Embedded Document nên chúng ta sẽ tiếp tục với các thao tác cơ bản của mô hình dữ liệu này.Embedded Document nên chúng ta sẽ tiếp tục với các thao tác cơ bản của mô hình dữ liệu này.

3. Thêm 1 Embedded Document vào 1 mảng

// retrieve my model
var Student = mongoose.model('Student');

// create a student
var student = new Student({ name: 'Cao Thanh Sang', age: 23 });

// create a project
student.projects.push({ title: 'Project 1', unit: 'NodeJs' });

student.save(function (err) {
    if (err) {
        console.log(err);
    } else {
        console.log('Success!');
    }
});

4. Xóa 1 Embedded Document

Student.findById(myId, function (err, student) {
    if (err) {
        console.log(err)
    } else {
        student.projects[0].remove();
        student.save(function (err) {
            // do something
        });
    };
});

5. Tìm Embedded Document theo id

DocumentArrays có method đặc biệt là id() để lọc các Embedded Document theo thuộc tính _id của chúngid() để lọc các Embedded Document theo thuộc tính _id của chúng

student.projects.id(my_id).remove();
student.save(function (err) {
    // embedded project with id `my_id` removed!
});

Bài viết đến đây kết thúc rồi!!! Mình xin cảm ơn các bạn đã đọc bài. Nếu có sai sót hoặc cách diễn đạt của mình sai thì hãy comment phía dưới nhé.

Tài liệu tham khảo:

  1. https://mongoosejs.com/docs/2.7.x/docs/embedded-documents.html
  2. https://docs.mongodb.com/manual/core/data-modeling-introduction/

Vui lòng xem trang trình điều khiển C# để biết thêm thông tin.MongoDB Manual

Đi

Haskell

Java

Vui lòng xem trang trình điều khiển Java để biết thêm thông tin.

Vui lòng xem trang trình điều khiển Node.js để biết thêm thông tin.

Perl

  • Vui lòng xem trang trình điều khiển Perl để biết thêm thông tin. save the

    //Project.js
    var Project = new Schema({
      title: String,
      unit: String,
      student: { type:Schema.ObjectId, ref: "Student" }
    });
    
    mongoose.model('Project', Project);
    
    3 field of one document in another document as a reference. Your application runs a second query to return the related data. These references are simple and sufficient for most use cases.

  • DBREF là các tài liệu tham khảo từ tài liệu này sang tài liệu khác bằng cách sử dụng giá trị của trường

    //Project.js
    var Project = new Schema({
      title: String,
      unit: String,
      student: { type:Schema.ObjectId, ref: "Student" }
    });
    
    mongoose.model('Project', Project);
    
    3 của tài liệu đầu tiên và tùy chọn tên cơ sở dữ liệu của nó, cũng như bất kỳ trường nào khác. DBREFS cho phép bạn dễ dàng tham khảo các tài liệu được lưu trữ trong nhiều bộ sưu tập hoặc cơ sở dữ liệu. are references from one document to another using the value of the first document's
    //Project.js
    var Project = new Schema({
      title: String,
      unit: String,
      student: { type:Schema.ObjectId, ref: "Student" }
    });
    
    mongoose.model('Project', Project);
    
    3 field, collection name, and, optionally, its database name, as well as any other fields. DBRefs allow you to more easily reference documents stored in multiple collections or databases.

Để giải quyết DBREFS, ứng dụng của bạn phải thực hiện các truy vấn bổ sung để trả về các tài liệu được tham chiếu. Một số trình điều khiển MongoDB cung cấp các phương pháp trợ giúp để cho phép DBREF được giải quyết thành các tài liệu, nhưng nó không tự động xảy ra.MongoDB drivers provide helper methods to enable DBRefs to be resolved into documents, but it doesn't happen automatically.

DBREF cung cấp một định dạng và loại phổ biến để thể hiện mối quan hệ giữa các tài liệu. Định dạng DBREF cũng cung cấp các ngữ nghĩa phổ biến để biểu diễn các liên kết giữa các tài liệu nếu cơ sở dữ liệu của bạn phải tương tác với nhiều khung và công cụ.

Trừ khi bạn có một lý do thuyết phục để sử dụng DBREF, hãy sử dụng các tài liệu tham khảo thủ công thay thế.

Một tài liệu tham khảo thủ công là thực tiễn bao gồm trường

//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
3 của một tài liệu trong một tài liệu khác. Ứng dụng sau đó có thể phát hành truy vấn thứ hai để giải quyết các trường được tham chiếu khi cần thiết.

Xem xét hoạt động sau để chèn hai tài liệu, sử dụng trường

//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
3 của tài liệu đầu tiên làm tài liệu tham khảo trong tài liệu thứ hai:

original_id = ObjectId()
db.places.insertOne({
"_id": original_id,
"name": "Broadway Center",
"url": "bc.example.net"
})
db.people.insertOne({
"name": "Erin",
"places_id": original_id,
"url": "bc.example.net/Erin"
})

Sau đó, khi một truy vấn trả về tài liệu từ bộ sưu tập

//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
7, nếu cần, hãy thực hiện truy vấn thứ hai cho tài liệu được tham chiếu bởi trường
//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
8 trong bộ sưu tập
//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
9.

Đối với gần như mọi trường hợp bạn muốn lưu trữ mối quan hệ giữa hai tài liệu, hãy sử dụng các tài liệu tham khảo thủ công. Các tài liệu tham khảo rất đơn giản để tạo và ứng dụng của bạn có thể giải quyết các tài liệu tham khảo khi cần thiết.manual references. The references are simple to create and your application can resolve references as needed.

Hạn chế duy nhất của liên kết thủ công là các tài liệu tham khảo này không truyền tải cơ sở dữ liệu và tên thu thập. Nếu bạn có tài liệu trong một bộ sưu tập duy nhất liên quan đến các tài liệu trong nhiều bộ sưu tập, bạn có thể cần xem xét sử dụng DBREFS.

DBREF là một quy ước để đại diện cho một tài liệu, thay vì một loại tham chiếu cụ thể. Chúng bao gồm tên của bộ sưu tập và trong một số trường hợp, tên cơ sở dữ liệu, ngoài giá trị từ trường

//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
3.

Tùy chọn, DBREFS có thể bao gồm bất kỳ số lượng các trường khác. Tên trường bổ sung phải tuân theo bất kỳ quy tắc nào cho tên trường áp đặt bởi phiên bản máy chủ.

DBREF có các trường sau:

//Student.js
var Student = new Schema({
  name: String,
  age: Number
});

mongoose.model('Student', Student);
1

Trường

//Student.js
var Student = new Schema({
  name: String,
  age: Number
});

mongoose.model('Student', Student);
1 giữ tên của bộ sưu tập nơi tài liệu được tham chiếu cư trú.

//Student.js
var Student = new Schema({
  name: String,
  age: Number
});

mongoose.model('Student', Student);
3

Trường

//Student.js
var Student = new Schema({
  name: String,
  age: Number
});

mongoose.model('Student', Student);
3 chứa giá trị của trường
//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
3 trong tài liệu được tham chiếu.

//Student.js
var Student = new Schema({
  name: String,
  age: Number
});

mongoose.model('Student', Student);
6

Optional.

Chứa tên của cơ sở dữ liệu nơi tài liệu được tham chiếu cư trú.

Thí dụ

Tài liệu DBREF giống với tài liệu sau:

{ "$ref" : , "$id" : , "$db" : }

Hãy xem xét một tài liệu từ một bộ sưu tập lưu trữ DBREF trong trường

//Student.js
var Student = new Schema({
  name: String,
  age: Number
});

mongoose.model('Student', Student);
7:

{
"_id" : ObjectId("5126bbf64aed4daf9e2ab771"),
// .. application fields
"creator" : {
"$ref" : "creators",
"$id" : ObjectId("5126bc054aed4daf9e2ab772"),
"$db" : "users",
"extraField" : "anything"
}
}

DBREF trong ví dụ này chỉ ra một tài liệu trong bộ sưu tập

//Student.js
var Student = new Schema({
  name: String,
  age: Number
});

mongoose.model('Student', Student);
8 của cơ sở dữ liệu
//Student.js
var Student = new Schema({
  name: String,
  age: Number
});

mongoose.model('Student', Student);
9 có
// retrieve my model
var Student = mongoose.model('Student');

// create a student
var student = new Student({ name: 'Cao Thanh Sang', age: 23 });

// create a project
student.projects.push({ title: 'Project 1', unit: 'NodeJs' });

student.save(function (err) {
    if (err) {
        console.log(err);
    } else {
        console.log('Success!');
    }
});
0 trong trường
//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
3 của nó. Nó cũng chứa một trường tùy chọn.

Ghi chú

Thứ tự của các trường trong các vấn đề DBREF và bạn phải sử dụng trình tự trên khi sử dụng DBREF.

Người lái xe

Hỗ trợ DBREF

Ghi chú

C

Không được hỗ trợ

Bạn có thể đi qua các tài liệu tham khảo bằng tay.

C++

Không được hỗ trợ

Bạn có thể đi qua các tài liệu tham khảo bằng tay.

C#

Được hỗ trợ

Vui lòng xem trang trình điều khiển C# để biết thêm thông tin.C# driver page for more information.

Đi

Không được hỗ trợ

Bạn có thể đi qua các tài liệu tham khảo bằng tay.

Được hỗ trợ

Không được hỗ trợ

Bạn có thể đi qua các tài liệu tham khảo bằng tay.

Được hỗ trợ

Được hỗ trợ

Vui lòng xem trang trình điều khiển C# để biết thêm thông tin.Java driver page for more information.

Node.js

Được hỗ trợ

Vui lòng xem trang trình điều khiển C# để biết thêm thông tin.Node.js driver page for more information.

Đi

Được hỗ trợ

Vui lòng xem trang trình điều khiển C# để biết thêm thông tin.Perl driver page for more information.

Đi

Không được hỗ trợ

Bạn có thể đi qua các tài liệu tham khảo bằng tay.

Được hỗ trợ

Được hỗ trợ

Vui lòng xem trang trình điều khiển C# để biết thêm thông tin.PyMongo driver page for more information.

Đi

Được hỗ trợ

Vui lòng xem trang trình điều khiển C# để biết thêm thông tin.Ruby driver page for more information.

Đi

Không được hỗ trợ

Bạn có thể đi qua các tài liệu tham khảo bằng tay.

Được hỗ trợmanual reference method for connecting two or more related documents. However, if you need to reference documents from multiple collections, consider using DBRefs.