Bài viết này sẽ hướng dẫn bạn cách thực hiện truy vấn MongoDB một cách linh hoạt bằng cách sử dụng các giá trị động. Chúng ta sẽ khám phá các phương pháp khác nhau để xây dựng truy vấn động, xử lý các điều kiện phức tạp và tối ưu hóa hiệu suất truy vấn. Việc làm chủ **truy vấn MongoDB** với giá trị động là một kỹ năng quan trọng đối với bất kỳ nhà phát triển nào làm việc với MongoDB, giúp bạn xây dựng các ứng dụng mạnh mẽ và linh hoạt hơn.
Trong nhiều ứng dụng thực tế, các điều kiện truy vấn không phải lúc nào cũng được xác định trước. Đôi khi, chúng phụ thuộc vào đầu vào của người dùng, dữ liệu từ các nguồn bên ngoài hoặc các yếu tố khác. **Truy vấn MongoDB** với giá trị động cho phép bạn xây dựng các truy vấn linh hoạt, đáp ứng các yêu cầu thay đổi của ứng dụng. Điều này đặc biệt quan trọng trong các ứng dụng phức tạp, nơi các điều kiện truy vấn có thể thay đổi tùy theo ngữ cảnh.
$expr
Biểu thức $expr
cho phép bạn sử dụng các toán tử truy vấn bên trong các biểu thức tổng hợp. Điều này rất hữu ích khi bạn cần so sánh các trường trong cùng một tài liệu hoặc thực hiện các phép tính dựa trên giá trị của các trường đó. Ví dụ, bạn có thể sử dụng $expr
để so sánh trường `progress_status_kd_updated_at` với một giá trị được tính toán động dựa trên trường `progress_status_kd`.
Ví dụ, giả sử bạn muốn tìm tất cả các đơn hàng mà thời gian cập nhật trạng thái (`progress_status_kd_updated_at`) nhỏ hơn hoặc bằng thời gian hiện tại trừ đi một khoảng thời gian nhất định, tùy thuộc vào trạng thái đơn hàng (`progress_status_kd`). Bạn có thể sử dụng biểu thức $expr
kết hợp với $cond
để thực hiện điều này:
db.collection.find({
progress_status_kd: { $in: [32, 33] },
ps_screen_preparing_n_packaging_permission: true,
$expr: {
$lte: [
"$progress_status_kd_updated_at",
{
$cond: [
{ $eq: ["$progress_status_kd", 33] },
{ $dateAdd: { startDate: "$$NOW", unit: "hour", amount: { $multiply: [-1, "$kdsConfig.ps_screen_preparing_time"] } } },
{ $dateAdd: { startDate: "$$NOW", unit: "minute", amount: { $multiply: [-1, "$kdsConfig.ps_screen_packaging_time"] } } }
]
}
]
}
})
Trong ví dụ này, $cond
được sử dụng để chọn khoảng thời gian trừ đi dựa trên giá trị của `progress_status_kd`. Nếu `progress_status_kd` bằng 33, chúng ta trừ đi `ps_screen_preparing_time` (tính bằng giờ); nếu không, chúng ta trừ đi `ps_screen_packaging_time` (tính bằng phút). Toán tử $dateAdd
cho phép ta cộng hoặc trừ một khoảng thời gian từ một ngày cụ thể. $$NOW
đại diện cho thời gian hiện tại.
$dateAdd
và $dateSubtract
(MongoDB 5.0+)Kể từ MongoDB phiên bản 5.0, bạn có thể sử dụng toán tử $dateAdd
để cộng hoặc trừ một khoảng thời gian từ một ngày cụ thể. Trong các phiên bản MongoDB mới hơn (8.0+), bạn có thể sử dụng `dateSubtract`. Điều này giúp bạn đơn giản hóa các truy vấn liên quan đến thời gian và thực hiện các phép tính ngày giờ một cách dễ dàng hơn. Điều này rất hữu ích khi bạn cần thực hiện các phép tính ngày giờ trực tiếp trong truy vấn.
Ví dụ, để trừ một khoảng thời gian động từ thời gian hiện tại, bạn có thể sử dụng $dateAdd
như sau:
db.collection.find({
progress_status_kd: { $in: [32, 33] },
ps_screen_preparing_n_packaging_permission: true,
$expr: {
$lte: [
"$progress_status_kd_updated_at",
{
$cond: [
{ $eq: ["$progress_status_kd", 33] },
{ $dateAdd: { startDate: "$$NOW", unit: "hour", amount: { $multiply: [-1, "$kdsConfig.ps_screen_preparing_time"] } } },
{ $dateAdd: { startDate: "$$NOW", unit: "minute", amount: { $multiply: [-1, "$kdsConfig.ps_screen_packaging_time"] } } }
]
}
]
}
})
Với MongoDB 8.0+, bạn có thể thay thế `$dateAdd` bằng `$dateSubtract` để có cú pháp rõ ràng hơn:
db.collection.find({
progress_status_kd: { $in: [32, 33] },
ps_screen_preparing_n_packaging_permission: true,
$expr: {
$lte: [
"$progress_status_kd_updated_at",
{
$cond: [
{ $eq: ["$progress_status_kd", 33] },
{ $dateSubtract: { startDate: "$$NOW", unit: "hour", amount: "$kdsConfig.ps_screen_preparing_time" } },
{ $dateSubtract: { startDate: "$$NOW", unit: "minute", amount: "$kdsConfig.ps_screen_packaging_time" } }
]
}
]
}
})
$where
(Cẩn Trọng)Toán tử $where
cho phép bạn thực thi mã JavaScript tùy ý trong truy vấn. Mặc dù điều này mang lại sự linh hoạt cao, nhưng nó có thể ảnh hưởng đến hiệu suất, đặc biệt là với các tập dữ liệu lớn. Do đó, nên hạn chế sử dụng $where
và chỉ sử dụng khi không có giải pháp nào khác.
Ví dụ:
db.collection.find({
$where: function() {
// Logic truy vấn phức tạp sử dụng JavaScript
return this.progress_status_kd === 33 && this.kdsConfig.ps_screen_preparing_time > 10;
}
})
Lưu ý quan trọng: Sử dụng `$where` có thể làm giảm hiệu suất truy vấn đáng kể. Hãy cân nhắc kỹ lưỡng trước khi sử dụng và tìm các giải pháp thay thế nếu có thể.
Một vấn đề phổ biến khi làm việc với **truy vấn MongoDB** và giá trị động là định dạng ngày tháng. MongoDB lưu trữ ngày tháng dưới dạng đối tượng `Date`, nhưng đôi khi dữ liệu ngày tháng có thể được lưu trữ dưới dạng chuỗi. Nếu bạn đang làm việc với dữ liệu ngày tháng dưới dạng chuỗi, bạn cần chuyển đổi nó sang đối tượng `Date` trước khi thực hiện so sánh.
Bạn có thể sử dụng toán tử `$toDate` để chuyển đổi chuỗi thành đối tượng `Date`:
db.collection.find({
$expr: {
$lte: [
{ $toDate: "$progress_status_kd_updated_at" },
{
$cond: [
{ $eq: ["$progress_status_kd", 33] },
{ $dateAdd: { startDate: "$$NOW", unit: "hour", amount: { $multiply: [-1, "$kdsConfig.ps_screen_preparing_time"] } } },
{ $dateAdd: { startDate: "$$NOW", unit: "minute", amount: { $multiply: [-1, "$kdsConfig.ps_screen_packaging_time"] } } }
]
}
]
}
})
Trong ví dụ này, `$toDate` được sử dụng để chuyển đổi trường `progress_status_kd_updated_at` từ chuỗi sang đối tượng `Date` trước khi so sánh.
Khi làm việc với **truy vấn MongoDB** và giá trị động, việc tối ưu hóa hiệu suất là rất quan trọng. Dưới đây là một số mẹo để cải thiện hiệu suất truy vấn:
$where
: Như đã đề cập ở trên, $where
có thể làm giảm hiệu suất truy vấn. Hãy cố gắng tìm các giải pháp thay thế nếu có thể.$eq
, $in
, $gt
, $lt
thay vì các toán tử phức tạp hơn khi có thể.**Truy vấn MongoDB** với giá trị động là một kỹ năng quan trọng cho bất kỳ nhà phát triển MongoDB nào. Bằng cách sử dụng các phương pháp và kỹ thuật được trình bày trong bài viết này, bạn có thể xây dựng các truy vấn linh hoạt, hiệu quả và đáp ứng các yêu cầu thay đổi của ứng dụng. Hãy nhớ luôn xem xét hiệu suất truy vấn và tối ưu hóa khi cần thiết để đảm bảo ứng dụng của bạn hoạt động trơn tru.
Bài viết liên quan