To, co hledáte, je poziční $
operátor a "projekce". Pro jedno pole musíte porovnat požadovaný prvek pole pomocí "tečkové notace", pro více než jedno pole použijte $elemMatch
:
db.products.find(
{ "items.date": "31.08.2014" },
{ "shop": 1, "name":1, "items.$": 1 }
)
Nebo $elemMatch
pro více než jedno odpovídající pole:
db.products.find(
{ "items": {
"$elemMatch": { "date": "31.08.2014", "purchasePrice": 1 }
}},
{ "shop": 1, "name":1, "items.$": 1 }
)
Ty však fungují pouze pro jeden prvek pole a vrátí se pouze jeden. Pokud chcete, aby se z vašich podmínek vrátil více než jeden prvek pole, pak potřebujete pokročilejší práci s agregačním rámcem.
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" }
}}
])
Nebo možná v kratší/rychlejší podobě od MongoDB 2.6, kde vaše pole položek obsahuje jedinečné položky:
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]
]
}
}}
])
Nebo případně pomocí $redact
, ale trochu vykonstruované:
db.products.aggregate([
{ "$match": { "items.date": "31.08.2014" } },
{ "$redact": {
"$cond": [
{ "$eq": [ { "$ifNull": [ "$date", "31.08.2014" ] }, "31.08.2014" ] },
"$$DESCEND",
"$$PRUNE"
]
}}
])
Modernější byste použili $filter
:
db.products.aggregate([
{ "$match": { "items.date": "31.08.2014" } },
{ "$addFields": {
"items": {
"input": "$items",
"cond": { "$eq": [ "$$this.date", "31.08.2014" ] }
}
}}
])
A s více podmínkami, $elemMatch
a $and
v rámci $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 ] }
]
}
}
}}
])
Záleží tedy jen na tom, zda vždy očekáváte shodu jednoho prvku nebo více prvků, a pak, který přístup je lepší. Ale kde je to možné, .find()
Metoda bude obecně rychlejší, protože postrádá režii ostatních operací, které v těchto posledních formulářích vůbec nezaostávají tak daleko.
Jako vedlejší poznámku, vaše "data" jsou reprezentována jako řetězce, což není příliš dobrý nápad do budoucna. Zvažte jejich změnu na správné Datum objektových typů, což vám v budoucnu velmi pomůže.