#mongodb #mongodb-query #aggregation-framework
#mongodb #mongodb-запрос #aggregation-framework
Вопрос:
У меня есть одна коллекция с именем ‘ctrlcharts’. например
{
"_id" : ObjectId("57fc695492af567031246736"),
"deviceId" : "A001",
"sensorId" : "S003",
"time" : "2016/10/11 12:23:50",
"charts" : [
{
"sensor" : "ch_11",
"value" : 120
},
{
"sensor" : "ch_12",
"value" : 150
}
]
}
Как фильтровать "sensor" : "ch_11"
и агрегировать данные из одной коллекции в другой формат с помощью MongoDB
например
{
"time" : "2016/10/11 12:23:50",
"sensor" : "ch_12",
"value" : 150
}
Я попробовал приведенный ниже код
db.ctrlcharts.aggregate([
{ $match: {"deviceId" : "A001", "sensorId" : "S003", "time" : "2016/10/11 12:23:50"}},
{ $project: {
_id: 0,
time : 1 ,
sensor : "$charts.sensor"
value : "$charts.value"
}
}
])
Но я получил результат в виде
{
"time" : "2016/10/11 12:23:50",
"sensor" : ["ch_11","ch_12"],
"value" : [120,150]
}
Спасибо
Комментарии:
1. что вы пробовали?
Ответ №1:
Вы старались изо всех сил ….просто используйте $unwind
db.ctrlcharts.aggregate(
{$unwind:"$charts"},
{$match: {"deviceId" :"A001", "charts.sensor":"ch_12", "time" : "2016/10/11 12:23:50"}},
{$project:{_id:0,time:1, sensor : "$charts.sensor", value :"$charts.value"}}).pretty()
Ответ №2:
Вы можете использовать $unwind (aggregation)
для разделения массива диаграмм.
db.ctrlcharts.aggregate( [ { $unwind : "$charts" } ] )
Это приведет к результату, подобному —
{ "_id" : ObjectId("57ff397a007c43ecacf10512"), "deviceId" : "A001", "sensorId" : "S003", "time" : "2016/10/11 12:23:50", "charts" : { "sensor" : "ch_11", "value" : 120 } }
{ "_id" : ObjectId("57ff397a007c43ecacf10512"), "deviceId" : "A001", "sensorId" : "S003", "time" : "2016/10/11 12:23:50", "charts" : { "sensor" : "ch_12", "value" : 150 } }
а затем используйте запрос соответствия
Ответ №3:
Используйте операторы $arrayElemAt
and $filter
для более эффективного запроса массива без необходимости $unwind
. Причина $unwind
, по которой это не так эффективно, заключается в том, что он создает декартово произведение документов, т.Е. Копию каждого документа на запись массива, что использует больше памяти (возможный объем памяти на конвейерах агрегации составляет 10% от общей памяти) и, следовательно, требует времени для создания, а также обработки документов в процессе выравнивания.
$filter
Вернет подмножество массива, которое содержит только элементы, соответствующие условию фильтра. Затем $arrayElemAt
оператор возвращает элемент из отфильтрованного массива с указанным индексом массива, чтобы предоставить вам нужный вам вложенный документ.
Необходимо еще $project
сгладить поля, чтобы получить желаемый результат:
db.ctrlcharts.aggregate([
{ "$match": {
"deviceId": "A001",
"sensorId": "S003",
"time": "2016/10/11 12:23:50",
"charts.sensor": "ch_11"
} },
{
"$project": {
"time": 1,
"chart": {
"$arrayElemAt": [
"$filter": {
"input": "$charts",
"as": "item",
"cond": { "$eq": ["$$item.sensor", "ch_11"] }
}, 0
]
}
}
},
{
"$project": {
"_id": 0,
"time": 1,
"sensor": "$chart.sensor"
"value": "$chart.value"
}
}
])