Những gì bạn đang tìm kiếm là vị trí $
toán tử và "phép chiếu". Đối với một trường, bạn cần đối sánh với phần tử mảng bắt buộc bằng cách sử dụng "ký hiệu dấu chấm", đối với nhiều trường, hãy sử dụng $elemMatch
:
db.products.find(
{ "items.date": "31.08.2014" },
{ "shop": 1, "name":1, "items.$": 1 }
)
Hoặc $elemMatch
cho nhiều trường phù hợp:
db.products.find(
{ "items": {
"$elemMatch": { "date": "31.08.2014", "purchasePrice": 1 }
}},
{ "shop": 1, "name":1, "items.$": 1 }
)
Tuy nhiên, chúng chỉ hoạt động cho một phần tử mảng duy nhất và chỉ một phần tử sẽ được trả về. Nếu bạn muốn nhiều hơn một phần tử mảng được trả về từ các điều kiện của mình thì bạn cần xử lý nâng cao hơn với khung tổng hợp.
db.products.aggregate([
{ "$match": { "items.date": "31.08.2014" } },
{ "$unwind": "$items" },
{ "$match": { "items.date": "31.08.2014" } },
{ "$group": {
"_id": "$_id",
"shop": { "$first": "$shop" },
"name": { "$first": "$name" },
"items": { "$push": "$items" }
}}
])
Hoặc có thể ở dạng ngắn hơn / nhanh hơn kể từ MongoDB 2.6 trong đó mảng các mục của bạn chứa các mục nhập duy nhất:
db.products.aggregate([
{ "$match": { "items.date": "31.08.2014" } },
{ "$project": {
"shop": 1,
"name": 1,
"items": {
"$setDifference": [
{ "$map": {
"input": "$items",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.date", "31.08.2014" ] },
"$$el",
false
]
}
}},
[false]
]
}
}}
])
Hoặc có thể với $redact
, nhưng có một chút giả thiết:
db.products.aggregate([
{ "$match": { "items.date": "31.08.2014" } },
{ "$redact": {
"$cond": [
{ "$eq": [ { "$ifNull": [ "$date", "31.08.2014" ] }, "31.08.2014" ] },
"$$DESCEND",
"$$PRUNE"
]
}}
])
Hiện đại hơn, bạn sẽ sử dụng $filter
:
db.products.aggregate([
{ "$match": { "items.date": "31.08.2014" } },
{ "$addFields": {
"items": {
"input": "$items",
"cond": { "$eq": [ "$$this.date", "31.08.2014" ] }
}
}}
])
Và với nhiều điều kiện, $elemMatch
và $and
trong $filter
:
db.products.aggregate([
{ "$match": {
"$elemMatch": { "date": "31.08.2014", "purchasePrice": 1 }
}},
{ "$addFields": {
"items": {
"input": "$items",
"cond": {
"$and": [
{ "$eq": [ "$$this.date", "31.08.2014" ] },
{ "$eq": [ "$$this.purchasePrice", 1 ] }
]
}
}
}}
])
Vì vậy, nó chỉ phụ thuộc vào việc bạn luôn mong đợi một phần tử duy nhất phù hợp hay nhiều phần tử, và sau đó cách tiếp cận nào tốt hơn. Nhưng nếu có thể thì .find()
phương pháp nói chung sẽ nhanh hơn vì nó không thiếu chi phí của các hoạt động khác, mà trong những hoạt động cuối cùng với biểu mẫu không bị tụt hậu xa như vậy chút nào.
Lưu ý thêm, "ngày tháng" của bạn được biểu diễn dưới dạng chuỗi, đây không phải là một ý kiến hay về sau. Cân nhắc thay đổi những điều này thành Ngày thích hợp loại đối tượng, điều này sẽ giúp bạn rất nhiều trong tương lai.