Я пытаюсь запросить вложенный вложенный документ, а затем вернуть только массив в этом вложенном документе через проекция . После запроса вы можете выбрать поля, которые вы хотите вернуть через проекцию. Я хочу использовать нативный функционал, потому что это возможно и самым чистым способом. Проблема в том, что он возвращает массивы в двух документах.
Я пробовал разные варианты запросов и проекций, но безрезультатно.
Модель пользователя
// Define station schema
const stationSchema = new mongoose.Schema({
mac: String,
stationName: String,
syncReadings: Boolean,
temperature: Array,
humidity: Array,
measures: [{
date: Date,
temperature: Number,
humidity: Number
}],
lastUpdated: Date
});
// Define user schema
var userSchema = mongoose.Schema({
apiKey: String,
stations : [stationSchema]
}, {
usePushEach: true
}
);
вызов API
app.get('/api/stations/:stationName/measures',function(req, res, next) {
var user = {
apiKey: req.user.apiKey
}
const query = {
apiKey: user.apiKey,
'stations.stationName': req.params.stationName
}
const options = {
'stations.$.measures': 1,
}
User.findOne(query, options)
.exec()
.then(stations => {
res.status(200).send(stations)
})
.catch(err => {
console.log(err);
res.status(400).send(err);
})
});
Ожидаемый результат
{
"_id": "5c39c99356bbf002fb092ce9",
"stations": [
{
"stationName": "livingroom",
"measures": [
{
"humidity": 60,
"temperature": 20,
"date": "2019-01-12T22:49:45.468Z",
"_id": "5c3a6f09fd357611f8d078a0"
},
{
"humidity": 60,
"temperature": 20,
"date": "2019-01-12T22:49:46.500Z",
"_id": "5c3a6f0afd357611f8d078a1"
},
{
"humidity": 60,
"temperature": 20,
"date": "2019-01-12T22:49:47.041Z",
"_id": "5c3a6f0bfd357611f8d078a2"
}
]
}
]
}
Фактический результат
{
"_id": "5c39c99356bbf002fb092ce9",
"stations": [
{
"stationName": "livingroom",
"measures": [
{
"humidity": 60,
"temperature": 20,
"date": "2019-01-12T22:49:45.468Z",
"_id": "5c3a6f09fd357611f8d078a0"
},
{
"humidity": 60,
"temperature": 20,
"date": "2019-01-12T22:49:46.500Z",
"_id": "5c3a6f0afd357611f8d078a1"
},
{
"humidity": 60,
"temperature": 20,
"date": "2019-01-12T22:49:47.041Z",
"_id": "5c3a6f0bfd357611f8d078a2"
}
]
},
******************************************************
// this whole object should not be returned
{
"stationName": "office",
"measures": []
}
******************************************************
]
}
редактировать
Приведенный ниже ответ с агрегацией работает, но я все еще нахожу странным, что мне понадобится так много кода. Если после обычного запроса я получаю тот же результат с ".stations [0] .measures" вместо всего конвейера агрегации:
.then(stations => {
res.status(200).send(stations.stations[0].measures)
})
То, как я читаю код, выше делает точно так же, как:
const options = {'stations.$.measures': 1}
Где знак доллара помещает в индекс 0, поскольку это был индекс станции, которая соответствует части запроса: stationName: "livingroom"
Может кто-нибудь объяснить?