Mảng đối tượng lồng nhau tra cứu MongoDB

Đối với điều này, hãy sử dụng $lookup. Thao tác này thực hiện phép nối ngoài bên trái với bộ sưu tập chưa được chia nhỏ trong cùng một cơ sở dữ liệu để lọc các tài liệu từ bộ sưu tập “đã nối” để xử lý

Trước tiên chúng ta hãy tạo một bộ sưu tập với các tài liệu -

> db.demo395.insertOne({Name:"Chris"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e5e782317aa3ef9ab8ab207")
}
> db.demo395.insertOne({Name:"David"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e5e782317aa3ef9ab8ab208")
}

Hiển thị tất cả các tài liệu từ một bộ sưu tập với sự trợ giúp của phương thức find() -

> db.demo395.find();

Điều này sẽ tạo ra đầu ra sau -

{ "_id" : ObjectId("5e5e782317aa3ef9ab8ab207"), "Name" : "Chris" }
{ "_id" : ObjectId("5e5e782317aa3ef9ab8ab208"), "Name" : "David" }

Hãy để chúng tôi tạo một bộ sưu tập thứ hai với các tài liệu -

> db.demo396.insertOne({"details" : [
..    ObjectId("5e5e782317aa3ef9ab8ab207"),
..    ObjectId("5e5e782317aa3ef9ab8ab208")
..    ]
.. }
.. )
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e5e787817aa3ef9ab8ab209")
}

Hiển thị tất cả các tài liệu từ một bộ sưu tập với sự trợ giúp của phương thức find() -

> db.demo396.find();

Điều này sẽ tạo ra đầu ra sau -

{ "_id" : ObjectId("5e5e787817aa3ef9ab8ab209"), "details" : [
ObjectId("5e5e782317aa3ef9ab8ab207"), ObjectId("5e5e782317aa3ef9ab8ab208") ] }

Sau đây là truy vấn để thực hiện $lookup tới mảng id của đối tượng -

> db.demo396.aggregate([
..    { "$lookup": {
..       "from": "demo395",
..       "let": { "details": "$details" },
..       "pipeline": [
..          { "$match": { "$expr": { "$in": [ "$_id", "$$details" ] } } }
..       ],
..       "as": "output"
..    }}
.. ])

Điều này sẽ tạo ra đầu ra sau -

{ "_id" : ObjectId("5e5e787817aa3ef9ab8ab209"), "details" : [ ObjectId("5e5e782317aa3ef9ab8ab207"), ObjectId("5e5e782317aa3ef9ab8ab208") ], "output" : [ { "_id" : ObjectId("5e5e782317aa3ef9ab8ab207"), "Name" : "Chris" }, { "_id" : ObjectId("5e5e782317aa3ef9ab8ab208"), "Name" : "David" } ] }

Mảng đối tượng lồng nhau tra cứu MongoDB


Mảng đối tượng lồng nhau tra cứu MongoDB

Nếu bạn đã làm việc với MongoDB, rất có thể bạn đã sử dụng các đường dẫn tổng hợp. Và đây là trường hợp sử dụng rất phổ biến mà bạn cần kết nối tài liệu từ bộ sưu tập này sang bộ sưu tập khác, hay còn gọi là 'Truy vấn tham gia' từ thời SQL của chúng tôi

Trước tiên hãy xây dựng tuyên bố vấn đề. Chúng tôi có 2 bộ sưu tập,

{
   ...
   _id: ObjectId(...),
   name: 'Macbook Pro M1',
   description: 'All systems pro.',
   price: 1200,
   ...
}
6 và
{
   ...
   _id: ObjectId(...),
   name: 'Macbook Pro M1',
   description: 'All systems pro.',
   price: 1200,
   ...
}
7.
Mỗi đơn đặt hàng đều có một số thông tin liên quan đến người dùng và danh sách các sản phẩm mà người dùng đã đặt cùng với số lượng của nó.

đối tượng đặt hàng mẫu

> db.demo395.find();
0

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

đối tượng sản phẩm mẫu

________số 8

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Kết quả chúng tôi muốn từ tổng hợp

> db.demo395.find();
2

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Ở đây bạn có thể thấy rằng chúng tôi đã thổi phồng chi tiết sản phẩm bên trong mảng sản phẩm.
Tại thời điểm viết bài này, tôi không thể tìm thấy bất kỳ cách dễ dàng và dễ dàng nào để đạt được điều này, vì vậy tôi quyết định tìm hiểu sâu hơn một chút.

Một điểm cần lưu ý ở đây, nếu mảng sản phẩm giống như

{
   ...
   _id: ObjectId(...),
   name: 'Macbook Pro M1',
   description: 'All systems pro.',
   price: 1200,
   ...
}
8 thì thật dễ dàng. Nhưng vì chúng tôi cũng cần cung cấp
{
   ...
   _id: ObjectId(...),
   name: 'Macbook Pro M1',
   description: 'All systems pro.',
   price: 1200,
   ...
}
9 cùng với productId, nên điều đó không khả thi lắm (ít nhất là với lược đồ hiện tại)

Vì vậy, hãy bắt đầu với giải pháp

Bước 1. Tách mảng

Sử dụng toán tử

> db.demo395.find();
20 để chia mảng sản phẩm sao cho mỗi tài liệu được tạo sẽ chỉ có một sản phẩm thay vì toàn bộ mảng

> db.demo395.find();
6

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Bây giờ mỗi đơn đặt hàng chưa được thực hiện của chúng tôi sẽ trông giống như thế này

> db.demo395.find();
7

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Điều này có vẻ đơn giản hơn, nhưng chờ đã, phần còn lại của các sản phẩm được đặt hàng ở đâu?
Hóa ra, việc sử dụng

> db.demo395.find();
20 sẽ chia một tài liệu thành nhiều tài liệu trong đó tất cả dữ liệu giống hệt nhau ngoại trừ .
Ở đây, nó sẽ chia tài liệu mẫu của chúng ta thành 2 tài liệu như sau

{ "_id" : ObjectId("5e5e782317aa3ef9ab8ab207"), "Name" : "Chris" }
{ "_id" : ObjectId("5e5e782317aa3ef9ab8ab208"), "Name" : "David" }
0

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Vì vậy, tôi hy vọng rõ ràng rằng nếu bạn có n đơn đặt hàng với m sản phẩm trong mỗi đơn hàng, nó sẽ tạo ra tổng số

> db.demo395.find();
23 tài liệu

Bước 2. Thổi phồng chi tiết sản phẩm

Đây là bước quan trọng, lấy chi tiết sản phẩm từ bộ sưu tập khác

{ "_id" : ObjectId("5e5e782317aa3ef9ab8ab207"), "Name" : "Chris" }
{ "_id" : ObjectId("5e5e782317aa3ef9ab8ab208"), "Name" : "David" }
2

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

bước này thổi phồng dữ liệu và làm cho nó trông giống như sau

{ "_id" : ObjectId("5e5e782317aa3ef9ab8ab207"), "Name" : "Chris" }
{ "_id" : ObjectId("5e5e782317aa3ef9ab8ab208"), "Name" : "David" }
3

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Nếu bạn nhận thấy một điều, sản phẩm bị thổi phồng, nhưng đó là một mảng thay vì một đối tượng. Lý do là, mongodb hy vọng rằng nhiều tài liệu trong bảng

{
   ...
   _id: ObjectId(...),
   name: 'Macbook Pro M1',
   description: 'All systems pro.',
   price: 1200,
   ...
}
7 có thể phù hợp với tiêu chí này và do đó, theo mặc định, đặt tất cả các tài liệu vào một mảng. Trong trường hợp của chúng tôi, chúng tôi biết nó sẽ là duy nhất, vì vậy chúng tôi có thể thư giãn nó ra

Bước 2a. Thư giãn sản phẩm bị thổi phồng

{ "_id" : ObjectId("5e5e782317aa3ef9ab8ab207"), "Name" : "Chris" }
{ "_id" : ObjectId("5e5e782317aa3ef9ab8ab208"), "Name" : "David" }
5

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Mát mẻ. chúng tôi đã có dữ liệu chúng tôi cần. Bây giờ chúng ta có thể hợp nhất các tài liệu đó để biến nó thành tài liệu gốc

Bước 3. Hợp nhất các tài liệu

chìa khóa cho bước này là

> db.demo395.find();
25. chúng tôi sẽ đẩy tất cả các sản phẩm vào một mảng

Nhưng, đây là một lưu ý nhỏ.
Để nhóm chúng lại với nhau, bạn cũng cần giữ nguyên tất cả các trường khác. như

> db.demo395.find();
26,
> db.demo395.find();
27 và
> db.demo395.find();
28.
Một cách là đặt mọi thứ vào
> db.demo395.find();
28 trong nhóm của bạn, đại loại như

> db.demo396.insertOne({"details" : [
..    ObjectId("5e5e782317aa3ef9ab8ab207"),
..    ObjectId("5e5e782317aa3ef9ab8ab208")
..    ]
.. }
.. )
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e5e787817aa3ef9ab8ab209")
}
1

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

NHƯNG.
còn 3 thiếu sót

  1. Khó thực hiện nếu tài liệu có các khóa khác nhau
  2. Khả năng cao quên/gõ nhầm bất kỳ lĩnh vực nào
  3. Nếu lược đồ bị thay đổi dù chỉ một chút, bạn cần xem lại quy trình và viết lại phần này một lần nữa

Là một kỹ sư điển hình tin tưởng vào việc viết 20 dòng thông minh để tránh 5 dòng mã hóa cứng, tôi đã nghĩ ra một cách để biến bit này thành bằng chứng trong tương lai

Ý tưởng chính là hợp nhất chỉ dựa trên cơ sở của

> db.demo395.find();
28, sau đó tra cứu chính nó để lấy một bản sao mới của tài liệu

Bước 3a. Tham gia trên cơ sở của
> db.demo395.find();
28

{
   ...
   _id: ObjectId(...),
   name: 'Macbook Pro M1',
   description: 'All systems pro.',
   price: 1200,
   ...
}
0

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Ở đây, tôi đang đẩy các phần tử lên

{
   ...
   _id: ObjectId(...),
   name: 'Macbook Pro M1',
   description: 'All systems pro.',
   price: 1200,
   ...
}
7 sau khi chọn chúng từ
{
   ...
   _id: ObjectId(...),
   name: 'Macbook Pro M1',
   description: 'All systems pro.',
   price: 1200,
   ...
}
7, nghe có vẻ khó hiểu, nhưng những gì nó làm là, nó lấy tất cả
{
   ...
   _id: ObjectId(...),
   name: 'Macbook Pro M1',
   description: 'All systems pro.',
   price: 1200,
   ...
}
7 từ các tài liệu hiện có, đặt chúng vào một mảng và cuối cùng gọi nó là sản phẩm

Bước 3b. Lấy một bản sao mới của các đơn đặt hàng để tái tạo

{
   ...
   _id: ObjectId(...),
   name: 'Macbook Pro M1',
   description: 'All systems pro.',
   price: 1200,
   ...
}
1

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Cái này khá đơn giản, không cần giải thích nhiều. Tại thời điểm này, tài liệu trông giống như thế này