Truy vấn mảng lồng nhau Mongodb

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 đăng đã 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 đề nằm ở dãy 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

post: {
genres: [{id: 1, title: 'one'}, {id: 2, title: 'two'}],
tags: [{id: 1, title: 'one'}, {id: 2, title: 'two'}]
}

Đ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ó

Phần 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

Làm cách nào để truy vấn các trường lồng nhau trong MongoDB?

Trong MongoDB, bạn có thể truy cập vào các trường tài liệu được lồng/nhúng của bộ sưu tập bằng cách sử dụng ký hiệu dấu chấm và khi bạn đang sử dụng ký hiệu dấu chấm, . Tài liệu. ba tài liệu chứa thông tin chi tiết về sinh viên ở dạng cặp trường-giá trị.

Làm cách nào để truy vấn một mảng đối tượng trong MongoDB?

Để tìm kiếm mảng đối tượng trong MongoDB, bạn có thể sử dụng toán tử $elemMatch . Toán tử này cho phép chúng ta tìm kiếm nhiều hơn một thành phần từ một đối tượng mảng.

Làm cách nào để cập nhật mảng đối tượng lồng nhau trong MongoDB?

Cập nhật mảng đối tượng lồng nhau .
db. thu thập. .
Toán tử $set thay thế giá trị của một trường bằng giá trị đã chỉ định
The filtered positional operator $[] identifies the array elements that match the arrayFilters conditions for an update operation..

Làm cách nào để chèn mảng đối tượng trong MongoDB?

Chèn mảng bên trong đối tượng trong MongoDB .
Tổng quan. MongoDB là cơ sở dữ liệu NoSQL định hướng tài liệu phân tán và mã nguồn mở phổ biến nhất. .
Khởi tạo cơ sở dữ liệu. .
Sử dụng MongoDB Shell. .
Thao tác chèn bằng mã trình điều khiển Java. .
Sử dụng DBObject. .
Sử dụng Tài liệu BSON. .
Phần kết luận