Использование MongoDB 3.4.4 и более новых версий:
db.collection.aggregate([
{ "$addFields": {
"data.visits.daily": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$data.visits.daily" },
"as": "el",
"cond": {
"$and": [
{ "$gte": ["$$el.k", "2018-09-06"] },
{ "$lte": ["$$el.k", "2018-09-07"] },
]
}
}
}
}
} }
])
Приведенный выше конвейер выдаст окончательный результат
{
"data" : {
"visits" : {
"daily" : {
"2018-09-06" : 2969,
"2018-09-07" : 2624
}
}
}
}
Пояснения
Конвейер может быть разложен, чтобы показать результаты каждого отдельного оператора.
$objectToArray
$objectToArray
позволяет преобразовывать документ с динамическимключи в массив, который содержит элемент для каждой пары поле / значение в исходном документе.Каждый элемент в массиве возврата является документом, который содержит два поля k и v.
Запуск конвейера только с оператором на $project
этапе
db.collection.aggregate([
{ "$project": {
"keys": { "$objectToArray": "$data.visits.daily" }
} }
])
урожайность
{
"_id" : ObjectId("5bab6d09b1951fef20a5dce4"),
"keys" : [
{
"k" : "2018-09-05",
"v" : 3586
},
{
"k" : "2018-09-06",
"v" : 2969
},
{
"k" : "2018-09-07",
"v" : 2624
},
{
"k" : "2018-09-08",
"v" : 2803
},
{
"k" : "2018-09-09",
"v" : 3439
},
{
"k" : "2018-09-10",
"v" : 3655
}
]
}
$filter
$filter
* 1049Оператор * действует как механизм фильтрации для массива, созданного оператором $objectToArray
, работает путем выбора подмножества массива для возврата на основе указанного условия, которое становитсяВаш запрос.
Рассмотрим следующий конвейер, который возвращает массив пары ключ / значение, который соответствует условию "2018-09-06" <= key <= "2018-09-07"
db.collection.aggregate([
{ "$project": {
"keys": {
"$filter": {
"input": { "$objectToArray": "$data.visits.daily" },
"as": "el",
"cond": {
"$and": [
{ "$gte": ["$$el.k", "2018-09-06"] },
{ "$lte": ["$$el.k", "2018-09-07"] },
]
}
}
}
} }
])
, что дает
{
"_id" : ObjectId("5bab6d09b1951fef20a5dce4"),
"keys" : [
{
"k" : "2018-09-06",
"v" : 2969
},
{
"k" : "2018-09-07",
"v" : 2624
}
]
}
$arrayToObject
Преобразует отфильтрованный массив выше из
[
{
"k" : "2018-09-06",
"v" : 2969
},
{
"k" : "2018-09-07",
"v" : 2624
}
]
в исходный документ с динамическим ключом
{
"2018-09-06" : 2969,
"2018-09-07" : 2624
}
так что при запуске конвейера
db.collection.aggregate([
{ "$project": {
"keys": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$data.visits.daily" },
"as": "el",
"cond": {
"$and": [
{ "$gte": ["$$el.k", "2018-09-06"] },
{ "$lte": ["$$el.k", "2018-09-07"] },
]
}
}
}
}
} }
])
будет получено
{
"_id" : ObjectId("5bab6d09b1951fef20a5dce4"),
"keys" : {
"2018-09-06" : 2969,
"2018-09-07" : 2624
}
}
Но, конечно, вы захотите сохранить исходную схему, то есть текущие поля, поэтому вам нужно будет использовать $addFields
вместо $project
трубопровода, используемого для иллюстрации.
$addFields
Это эквивалентно этапу $project
, который явно указывает все существующие поля во входных документах и добавляет новые поля.Указание существующего имени поля в операции $addFields
приводит к замене исходного поля, и вам нужно будет использовать точечную нотацию для обновления встроенного поля data.visits.daily с помощьюдинамические клавиши.