Để tìm document mà mảng chứa chuỗi là substring của một từ cho trước, dùng aggregate với $expr, $map, $indexOfBytes và $anyElementTrue.
Dữ liệu mẫu
> db.demo90.insertOne({ "words": ["john", "jace"] });
{ "acknowledged" : true, "insertedId" : ObjectId("5e2c1ada79799acab037af56") }
> db.demo90.insertOne({ "words": ["sam", "adam"] });
{ "acknowledged" : true, "insertedId" : ObjectId("5e2c1adb79799acab037af57") }
Truy vấn aggregate phức tạp
Tìm document có phần tử trong mảng "words" là substring của "john":
> db.demo90.aggregate([
{ $match: {
$expr: {
$anyElementTrue: {
$map: {
input: "$words",
as: "j",
in: {
$ne: [ -1, { $indexOfBytes: [ "john", "$$j" ] } ]
}
}
}
}
}}
]);
Kết quả
{ "_id" : ObjectId("5e2c1ada79799acab037af56"), "words" : [ "john", "jace" ] }
Giải thích logic:
$map: Duyệt từng phần tử$$jtrong mảng$words$indexOfBytes: ["john", "$$j"]: Tìm vị trí$$jtrong chuỗi "john". Trả về -1 nếu không tìm thấy$ne: [-1, ...]: True nếu tìm thấy (khác -1)$anyElementTrue: True nếu ít nhất một phần tử trong mảng kết quả là true$expr+$match: Lọc document thỏa mãn biểu thức
Lưu ý: Cách này phức tạp. Nếu chỉ cần khớp chính xác, dùng {words: "john"}. Nếu cần regex, dùng {words: /john/}.