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,
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 – 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 – 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
- 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
- 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
- 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