Chúng tôi có thể thực hiện phép nối trong MongoDB không?

Một trong những điểm khác biệt lớn nhất giữa cơ sở dữ liệu SQL và NoSQL là THAM GIA. Trong cơ sở dữ liệu quan hệ, mệnh đề THAM GIA SQL cho phép bạn kết hợp các hàng từ hai hoặc nhiều bảng bằng cách sử dụng một trường chung giữa chúng. Ví dụ: nếu bạn có bảng

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
3 và
{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
4, bạn có thể viết các lệnh SQL chẳng hạn như

SELECT book.title, publisher.name
FROM book
LEFT JOIN book.publisher_id ON publisher.id;

Nói cách khác, bảng

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
5 có trường
{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
6 tham chiếu trường
{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
7 trong bảng
{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
8

Điều này là thực tế, vì một nhà xuất bản có thể cung cấp hàng nghìn cuốn sách. Nếu chúng tôi cần cập nhật thông tin chi tiết của nhà xuất bản, chúng tôi có thể thay đổi một bản ghi. Dư thừa dữ liệu được giảm thiểu vì chúng tôi không cần lặp lại thông tin nhà xuất bản cho mọi cuốn sách. Kỹ thuật này được gọi là chuẩn hóa

Cơ sở dữ liệu SQL cung cấp một loạt các tính năng chuẩn hóa và ràng buộc để đảm bảo các mối quan hệ được duy trì

NoSQL == Không THAM GIA?

Không phải lúc nào…

Cơ sở dữ liệu hướng tài liệu như MongoDB được thiết kế để lưu trữ dữ liệu không chuẩn hóa. Lý tưởng nhất, không nên có mối quan hệ giữa các bộ sưu tập. Nếu cùng một dữ liệu được yêu cầu trong hai hoặc nhiều tài liệu, nó phải được lặp lại

Điều này có thể gây khó chịu vì có một số tình huống mà bạn không bao giờ cần dữ liệu quan hệ. May mắn thay, MongoDB 3. 2 giới thiệu một toán tử

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
9 mới có thể thực hiện thao tác giống như LEFT-OUTER-JOIN trên hai hoặc nhiều tập hợp. Nhưng có một nhược điểm…

Tập hợp MongoDB

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
9 chỉ được phép trong các hoạt động tổng hợp. Hãy coi đây là một hệ thống các toán tử truy vấn, lọc và nhóm một kết quả. Đầu ra của một toán tử được sử dụng làm đầu vào cho tiếp theo

Tổng hợp khó hiểu hơn các truy vấn

{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
1 đơn giản hơn và nhìn chung sẽ chạy chậm hơn. Tuy nhiên, chúng mạnh mẽ và là một tùy chọn vô giá cho các hoạt động tìm kiếm phức tạp

Tập hợp được giải thích tốt nhất với một ví dụ. Giả sử chúng ta đang tạo một nền tảng truyền thông xã hội với bộ sưu tập

{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
2. Nó lưu trữ mọi chi tiết của người dùng trong các tài liệu riêng biệt. Ví dụ

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}

Chúng tôi có thể thêm bao nhiêu trường nếu cần, nhưng tất cả các tài liệu MongoDB đều yêu cầu trường

{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
3 có giá trị duy nhất.
{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
3 tương tự như khóa chính của SQL và sẽ được chèn tự động nếu cần

Mạng xã hội của chúng tôi hiện yêu cầu bộ sưu tập

{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
5, nơi lưu trữ nhiều cập nhật sâu sắc từ người dùng. Các tài liệu lưu trữ văn bản, ngày tháng, xếp hạng và tham chiếu đến người dùng đã viết nó trong trường
{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
6

{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}

Bây giờ chúng tôi muốn hiển thị 20 bài đăng cuối cùng có xếp hạng “quan trọng” từ tất cả người dùng theo thứ tự thời gian đảo ngược. Mỗi tài liệu được trả lại phải chứa văn bản, thời gian của bài đăng, tên và quốc gia của người dùng được liên kết

Truy vấn tổng hợp MongoDB được thông qua một mảng các toán tử đường ống xác định từng thao tác theo thứ tự. Đầu tiên, chúng ta cần trích xuất tất cả các tài liệu từ bộ sưu tập

{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
5 có xếp hạng chính xác bằng cách sử dụng bộ lọc
{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
8

{ "$match": { "rating": "important" } }

Bây giờ chúng ta phải sắp xếp các mục phù hợp theo thứ tự ngày ngược lại bằng cách sử dụng toán tử

{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
9

{ "$sort": { "date": -1 } }

Vì chúng tôi chỉ yêu cầu hai mươi bài đăng, nên chúng tôi có thể áp dụng giai đoạn

{ "$match": { "rating": "important" } }
0 để MongoDB chỉ cần xử lý dữ liệu mà chúng tôi muốn

{ "$limit": 20 }

Bây giờ chúng ta có thể tham gia dữ liệu từ bộ sưu tập

{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
2 bằng cách sử dụng mới. Nó yêu cầu một đối tượng có bốn tham số

  • { "$match": { "rating": "important" } }
    
    3. trường tra cứu trong tài liệu đầu vào
  • { "$match": { "rating": "important" } }
    
    4. bộ sưu tập để tham gia
  • { "$match": { "rating": "important" } }
    
    5. trường cần tra cứu trong bộ sưu tập
    { "$match": { "rating": "important" } }
    
    4
  • { "$match": { "rating": "important" } }
    
    7. tên của trường đầu ra

Do đó, nhà điều hành của chúng tôi là

{ "$lookup": {
  "localField": "user_id",
  "from": "user",
  "foreignField": "_id",
  "as": "userinfo"
} }

Điều này sẽ tạo ra một trường mới trong đầu ra của chúng tôi có tên là

{ "$match": { "rating": "important" } }
8. Nó chứa một mảng trong đó mỗi giá trị khớp với tài liệu
{
  "_id": ObjectID("17c9812acff9ac0bba018cc1"),
  "user_id": ObjectID("45b83bda421238c76f5c1969"),
  "date: ISODate("2016-09-05T03:05:00.123Z"),
  "text": "My life story so far",
  "rating": "important"
}
2

"userinfo": [
  { "name": "User One", ... }
]

Chúng tôi có mối quan hệ một đối một giữa

{ "$sort": { "date": -1 } }
0 và
{ "$sort": { "date": -1 } }
1, vì một bài đăng chỉ có thể có một tác giả. Do đó, mảng
{ "$match": { "rating": "important" } }
8 của chúng ta sẽ chỉ chứa một mục. Chúng ta có thể sử dụng toán tử
{ "$sort": { "date": -1 } }
3 để giải cấu trúc nó thành một tài liệu con

{ "$unwind": "$userinfo" }

Đầu ra bây giờ sẽ được chuyển đổi sang định dạng thực tế hơn, có thể áp dụng thêm các toán tử

"userinfo": {
  "name": "User One",
  "email: "userone@email.com",}

Cuối cùng, chúng tôi có thể trả lại văn bản, thời gian của bài đăng, tên và quốc gia của người dùng bằng cách sử dụng giai đoạn

{ "$sort": { "date": -1 } }
4 trong quy trình

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
0

Để tất cả chúng cùng nhau

Truy vấn tổng hợp cuối cùng của chúng tôi khớp với các bài đăng, sắp xếp theo thứ tự, giới hạn ở 20 mục mới nhất, kết hợp dữ liệu người dùng, làm phẳng mảng người dùng và chỉ trả về các trường cần thiết. Lệnh đầy đủ

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
1

Kết quả là một bộ sưu tập lên đến hai mươi tài liệu. Ví dụ

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
2

Tuyệt vời. Cuối cùng tôi cũng có thể chuyển sang NoSQL

MongoDB

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
9 rất hữu ích và mạnh mẽ, nhưng ngay cả ví dụ cơ bản này cũng yêu cầu một truy vấn tổng hợp phức tạp. Nó không phải là sự thay thế cho mệnh đề THAM GIA mạnh mẽ hơn được cung cấp trong SQL. MongoDB cũng không đưa ra các ràng buộc;

Lý tưởng nhất là toán tử

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
9 không được yêu cầu thường xuyên. Nếu bạn cần nó nhiều, có thể bạn đang sử dụng sai kho lưu trữ dữ liệu…

Nếu bạn có dữ liệu quan hệ, hãy sử dụng cơ sở dữ liệu quan hệ (SQL)

Điều đó nói rằng,

{
  "_id": ObjectID("45b83bda421238c76f5c1969"),
  "name": "User One",
  "email: "userone@email.com",
  "country": "UK",
  "dob": ISODate("1999-09-13T00:00:00.000Z")
}
9 là một bổ sung đáng hoan nghênh cho MongoDB 3. 2. Nó có thể khắc phục một số vấn đề khó chịu hơn khi sử dụng một lượng nhỏ dữ liệu quan hệ trong cơ sở dữ liệu NoSQL

Chia sẻ bài viết này

Craig Buckler

Craig là một nhà tư vấn web tự do ở Vương quốc Anh, người đã xây dựng trang đầu tiên của mình cho IE2. 0 vào năm 1995. Kể từ thời điểm đó, anh ấy đã ủng hộ các tiêu chuẩn, khả năng truy cập và các kỹ thuật HTML5 thực hành tốt nhất. Anh ấy đã tạo các thông số kỹ thuật doanh nghiệp, trang web và ứng dụng trực tuyến cho các công ty và tổ chức bao gồm Nghị viện Vương quốc Anh, Nghị viện Châu Âu, Bộ Năng lượng & Biến đổi Khí hậu, Microsoft, v.v. Anh ấy đã viết hơn 1.000 bài báo cho SitePoint và bạn có thể tìm thấy anh ấy @craigbuckler

Tại sao phép nối không được sử dụng trong MongoDB?

Trong MongoDB, một mẫu phổ biến là nhúng. Trong quan hệ khi bình thường hóa mọi thứ được chia thành nhiều phần. Thông thường trong mongo, các phần này kết thúc bằng một tài liệu duy nhất , vì vậy dù sao cũng không cần tham gia.

Chúng ta có thể tham gia hai bảng trong MongoDB không?

Thao tác THAM GIA có thể được thực hiện trong cơ sở dữ liệu SQL giữa hai bảng trong cùng một cơ sở dữ liệu hoặc khác nhau. Mặt khác, Thao tác THAM GIA trong MongoDB có thể được thực hiện giữa các bộ sưu tập được triển khai trong một cơ sở dữ liệu tương tự, mặc dù trường hợp là khác nhau .

Chúng tôi có thể thực hiện phép nối trên NoSQL không?

Mệnh đề THAM GIA được sử dụng để kết hợp các hàng từ hai hoặc nhiều bảng, dựa trên cột liên quan giữa chúng. Các phép nối chủ yếu được sử dụng trong Cơ sở dữ liệu Oracle NoSQL khi người dùng đang cố trích xuất dữ liệu từ các bảng có mối quan hệ phân cấp giữa chúng .

MongoDB có hỗ trợ tham gia truy vấn giữa các bộ sưu tập không?

6, Mongodb không hỗ trợ tham gia truy vấn như mysql