Mongodb truy vấn mảng đối tượng lồng nhau

Hôm nay trong bài viết này, chúng ta sẽ xem cách MongoDB-Truy vấn mảng được lồng sâu có chứa một giá trị cụ thể

Hôm nay trong bài viết này, chúng tôi sẽ đề cập đến các khía cạnh dưới đây,

  • MongoDB – Tìm tài liệu từ phần tử mảng lồng nhau
  • MongoDB – Tìm tài liệu theo chiều dài mảng lồng nhau
  • MongoDB – Tìm tài liệu có mảng lồng nhau bằng cách chỉ định nhiều điều kiện

Chúng tôi sẽ trình bày bên dưới một vài tình huống cụ thể như xử lý các phần tử kiểu mảng [],

  • Nhận tài liệu dựa trên kích thước mảng lồng nhau phù hợp i. e nơi kích thước mảng lớn hơn hoặc nhỏ hơn kích thước đã chỉ định
  • Tìm mảng chỉ chứa các giá trị cụ thể
  • Chỉ định điều kiện cho các phần tử mảng

Lược đồ mẫu như dưới đây,

Mongodb truy vấn mảng đối tượng lồng nhau

Trong ví dụ trên, chúng ta có hai mảng lồng nhau Sách mẫu [] và Danh mục []

MongoDB – Tìm tài liệu từ phần tử mảng lồng nhau

Yêu cầu

Mẫu 3 mảng lồng nhau,

{ <array-field1>.<array-field2>.<array-field3>.<Field-Name>: {<value> }

Ví dụ dưới đây cho thấy một bộ lọc mảng nơi chúng ta lấy danh sách các tài liệu trong đó giá trị của phần tử mảng lồng nhau i. e danh mục [] bằng với giá trị được chỉ định

{'Books.category.key': 'test2-1'}

Thí dụ

Mongodb truy vấn mảng đối tượng lồng nhau

MongoDB – Tìm tài liệu theo chiều dài mảng lồng nhau

Yêu cầu

{ <array-field1>.<array-field2: {$size :<size-specified> }

Thí dụ

Ví dụ dưới đây cho thấy một bộ lọc mảng nơi chúng tôi lấy danh sách các tài liệu dựa trên kích thước mảng i. e kích thước danh mục [] bằng với kích thước được chỉ định

{'Books.category': {$size:2}}
Mongodb truy vấn mảng đối tượng lồng nhau

MongoDB – Tìm tài liệu có mảng lồng nhau bằng cách chỉ định nhiều điều kiện

Thí dụ

Mảng truy vấn MongoDB với các trường chứa một chuỗi đã cho,

{'Books.category.key': {$regex: '-'}}

Truy vấn trên trả về các bản ghi trong đó thuộc tính “Khóa” của phần tử mảng có giá trị khớp hoặc chứa “-“

Năm 2019 mình bắt đầu viết fanfic. com. Đó là mạng xã hội nhà văn / độc giả tiểu thuyết nói tiếng Nga. Đã dành khoảng một tháng để suy nghĩ về cách cấu trúc kiến ​​trúc của ứng dụng web. Ban đầu, tôi không biết chính xác mình đang làm gì. Ban đầu, nó có vẻ là một dự án phụ nhỏ trong vài tháng

Khi bắt đầu mình quyết định chọn MEAN full-stack (MongoDB, Angular, ExpressJs, NodeJs). Tuy nhiên, thật là một vấn đề nan giải khi chọn MySQL hay MongoDB. Bởi vì trước đây tôi đã có một số kinh nghiệm với MySQL và tôi biết cơ sở dữ liệu SQL chiếm thị phần lớn trong các dự án web. MongoDB được chọn vì nó dựa trên các đối tượng javascript, do đó, việc sử dụng trên ngăn xếp hiện tại là điều đương nhiên

Phần lớn nhất của ứng dụng web dựa trên các bài đăng. Chúng có thể thuộc các loại khác nhau và bao gồm rất nhiều tham số. Chẳng hạn như xếp hạng độ tuổi, thể loại, thẻ, v.v.

Hiểu rằng cơ sở dữ liệu phải linh hoạt, tôi quyết định tránh các mảng đối tượng lồng nhau. Bởi vì điều đó đã tạo ra nguy cơ sai lệch giữa các bộ sưu tập. Ví dụ: có một bài đăng có các đối tượng mảng thể loại. Thể loại chứa tiêu đề và id. Nhưng đồng thời, có một bộ sưu tập thể loại. Nơi tất cả các thể loại được liệt kê. Chúng tôi sử dụng nó khi tạo bài viết mới

post: {
genres: [id1, id2, id3],
tags: [id1, id2, id3]
}

Bây giờ, điều gì sẽ xảy ra nếu chúng ta đổi tên một thể loại? . Vì vậy, chúng tôi kết thúc với một bài đăng chứa thể loại hiện có

Có, bạn có thể nói mỗi khi chúng tôi cập nhật thể loại, chúng tôi có thể cập nhật tất cả các bài đăng có chứa thể loại này. Mặc dù tôi muốn tránh tải lỗi thời này trên cơ sở dữ liệu

Cách được chọn là chỉ lưu trữ trong bài đăng một mảng ID của các thể loại. Nó dường như là giải pháp hiệu quả nhất. Dù sao, nó vẫn tối ưu hơn là đi theo cách SQL và có ba bộ sưu tập. bài viết, thể loại, hậu thể loại

Vấn đề

Trang web đã được phát hành và hoạt động đủ tốt. Ngay cả trên mỗi yêu cầu, nó vẫn điền vào tất cả các bài đăng có xếp hạng độ tuổi, thể loại, v.v. Kết quả là ở giao diện người dùng, tôi đã nhận được đầy đủ các đối tượng và không cần chạy thêm truy vấn

Tuy nhiên, sau một vài tháng, số lượng bài viết đã tăng lên. Chúng tôi bắt đầu đề cập đến thời gian tải chậm. Sau khi dành một chút thời gian cho cuộc điều tra đã tìm ra vấn đề là gì. Và vấn đề là ở một mảng ID. Mỗi bài đăng chứa tối đa mười mảng lồng nhau như vậy. Có nghĩa là mỗi bài đăng phải chạy mười lệnh dân số

PostModel.find({}).populate(‘genres’).populate(‘tags’).populate(‘ageRating’).exec();

Đó không phải là vấn đề duy nhất. Cách chúng tôi chạy các truy vấn tìm kiếm trên các bài đăng cũng bị ảnh hưởng bởi cách chúng tôi lưu trữ các ID lồng nhau. Mỗi khi chúng tôi thực hiện tìm kiếm trên trang web, nó đang tìm kiếm tiêu đề thẻ, sau đó chúng tôi lấy ID và chạy truy vấn bài đăng

const tagsFound = await TagModel.find({‘title’: { $in: keywordsRegArr }}).exec();
const tagsIdsArr = tagsFound.map( tag=> tag._id );
PostModel.find({tags:tagsIdsArr}).exec();

Ngoài hiệu suất tải trang, chúng tôi thấy máy chủ MongoDB Atlas của chúng tôi đang tính phí quá nhiều

Làm thế nào nó đã được giải quyết?

Sau một thời gian dài tranh luận với chính mình, tôi thấy rằng giải pháp tối ưu nhất sẽ là lưu trữ đầy đủ các đối tượng bên trong mỗi bài đăng. Vâng, đó là tăng kích thước cơ sở dữ liệu. Tuy nhiên, nó đang giải quyết vấn đề chính về hiệu suất và truy vấn

Bây giờ bộ sưu tập bài viết nhìn theo cách này

________số 8

Điều đó có nghĩa là bây giờ mỗi khi chúng tôi tìm kiếm các bài đăng, chúng tôi không cần phải tìm kiếm các thẻ để lấy ID của chúng. Bây giờ nó chỉ đang chạy tìm kiếm văn bản trên tất cả các bài đăng

Một điều quan trọng hơn đã được thêm vào là bộ nhớ đệm. Đối với cái đó, tôi đã sử dụng gói npm nút-cache. Một phần của các truy vấn được lưu trữ trên NodeJs. Bằng cách đó, chúng tôi giảm tải cho cơ sở dữ liệu. Một số yêu cầu được lưu vào bộ đệm trong nhiều giờ, một số trong vài phút

Kết quả

Như đã nói, bây giờ chúng tôi đã có thể chạy truy vấn tìm kiếm văn bản và tránh được nhiều quần thể

Các đối tượng bài đăng được lấy trực tiếp từ bộ sưu tập bài đăng mà không cần bất kỳ thao tác nào

Kết quả là thời gian truy vấn và tải đã giảm ít nhất bốn lần. Và nó trên cơ sở dữ liệu hiện tại so với các mạng xã hội là nhỏ

nhược điểm

  1. Bây giờ mỗi khi chúng tôi thay đổi thể loại, xếp hạng độ tuổi, v.v., chúng tôi cần cập nhật tất cả các bài đăng có chứa các đối tượng này. Nhưng những mặt hàng này hiếm khi thay đổi, vì vậy chúng tôi có thể hấp thụ cái này
  2. Sau đó, tôi cũng phải sửa đổi các truy vấn tìm kiếm từ ứng dụng khách. Bởi vì bộ sưu tập sau chứa một mảng đối tượng lồng nhau thay vì một mảng ID
  3. Kích thước lưu trữ tăng. Cuối cùng, kích thước cơ sở dữ liệu không tăng đáng kể. Chúng tôi thậm chí không đề cập đến nó

Sự kết luận

Dự án đã được phát hành một năm trước. Hiện tại chúng tôi có 22 nghìn người dùng và con số này đang tăng lên. Chúng tôi có rất nhiều tính năng được triển khai, mặc dù nhiều tính năng khác đang được phát triển. Có rất nhiều vấn đề chúng ta gặp trên đường. Tuy nhiên, vượt qua chúng và chinh phục những đỉnh núi tiếp theo

Bạn có thể có một mảng đối tượng trong MongoDB không?

Trong mô hình tài liệu của MongoDB, a 1. N dữ liệu mối quan hệ có thể được lưu trữ trong một bộ sưu tập ; . Dữ liệu liên quan được lưu trữ cùng nhau và có thể được truy cập (và cập nhật) cùng nhau. Các nhận xét được lưu trữ dưới dạng một mảng; .

$all trong MongoDB là gì?

$all. Toán tử $all chọn các tài liệu có giá trị của trường là một mảng chứa tất cả các phần tử đã chỉ định .

Tại sao chúng tôi sử dụng thư giãn trong MongoDB?

Toán tử giai đoạn $unwind MongoDB được sử dụng để giải cấu trúc trường mảng từ tài liệu đầu vào để xuất tài liệu cho từng phần tử . Mọi tài liệu đầu ra là tài liệu đầu vào với giá trị của trường mảng được thay thế bằng phần tử.

MongoDB elemMatch là gì?

Định nghĩa. $elemMatch. Toán tử $elemMatch khớp các tài liệu chứa trường mảng với ít nhất một phần tử khớp với tất cả các tiêu chí truy vấn đã chỉ định .