Во-первых, запросы к вложенным массивам всегда могут показаться утомительными.
Рассмотрим следующую коллекцию (как предложено в комментариях к этому посту ):
[
{
"IdVar": "60502",
"dates": [
{
"start": new Date("2017-03-01"),
"end": new Date("2017-04-01")
},
{
"start": new Date("2018-04-01"),
"end": new Date("2018-06-01")
}
]
},
{
"IdVar": "1337",
"dates": [
{
"start": new Date("2016-08-01"),
"end": new Date("2016-09-01")
},
{
"start": new Date("2015-04-01"),
"end": new Date("2015-06-01")
}
]
}
]
Вы хотите получить только те документы, даты которых, скажем, в 2017 году. Для этого вы можете использовать оператор $elemMatch
:
db.collection.find({
dates: {
$elemMatch: {
start: {
$gte: ISODate("2017-01-01T00:00:00Z"),
$lte: ISODate("2017-12-31T00:00:00Z")
}
}
}
})
... но, как вы справедливо заявили, это вернет вам документ полностью, без изменений. Во многих случаях это будет соответствовать вашим потребностям. Возможно, вы все равно захотите спроектировать поля вашего документа в соответствии с вашим запросом : простой способ выразить это - сказать, что проекция - это SQL-эквивалент SELECT
и запрос WHERE
.
В качестве примера, следующее будет возвращать только поле IdVar
каждого документа, соответствующего моему запросу:
db.collection.find({
dates: {
$elemMatch: {
start: {
$gte: ISODate("2017-01-01T00:00:00Z"),
$lte: ISODate("2017-12-31T00:00:00Z")
}
}
}
},
// Project your document's fields here:
{
IdVar: true
})
... вернется:
[
{
"IdVar": "60502",
"_id": ObjectId("5a934e000102030405000000")
}
]
Аналогично запросу вы можете использовать (почти) все операторы Монго в полях проекции.
Оператор $
также очень удобен при работе с вложенными массивами. Следующий код вернет то, что вам нужно, попробуйте ( MongoPlayground ):
db.collection.find({
dates: {
$elemMatch: {
start: {
$gte: ISODate("2017-01-01T00:00:00Z"),
$lte: ISODate("2017-12-31T00:00:00Z")
}
}
}
},
{
"dates.$": 1
})