Node.js MongoDB对子文档数组的查询和投影也会返回另一个文档的数组
我试图查询嵌入的子文档,然后通过返回该子文档中的数组。查询后,您可以选择希望通过投影返回的字段。我想使用本机功能,因为这是可能的,也是最干净的方式。问题是它返回两个文档中的数组 我尝试了不同的查询和投影选项,但没有结果Node.js MongoDB对子文档数组的查询和投影也会返回另一个文档的数组,node.js,mongodb,express,Node.js,Mongodb,Express,我试图查询嵌入的子文档,然后通过返回该子文档中的数组。查询后,您可以选择希望通过投影返回的字段。我想使用本机功能,因为这是可能的,也是最干净的方式。问题是它返回两个文档中的数组 我尝试了不同的查询和投影选项,但没有结果 用户模型 // Define station schema const stationSchema = new mongoose.Schema({ mac: String,
用户模型
// 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
}
);
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);
})
});
api调用
// 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
}
);
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": []
}
******************************************************
]
}
实际结果
{
"_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”
有人能解释一下吗?运算符将查询结果中数组字段的内容限制为仅包含与$elemMatch条件匹配的第一个元素
在选择查询中尝试$elemMatch,如下所示:
const query = {
apiKey: user.apiKey,
'stations.stationName': req.params.stationName
}
const options = {
'stations' : {$elemMatch: { 'stationName' : req.params.stationName }}
}
这并不是用
mongoose
来描述的,但这将在一个或多个文档中的站点数组中找到特定的站点名称,并仅返回度量值
数组:
db.foo.aggregate([
// First, find the docs we are looking for:
{$match: {"stations.stationName": "livingroom"}}
// Got the doc; now need to fish out ONLY the desired station. The filter will
// will return an array so use arrayElemAt 0 to extract the object at offset 0.
// Call this intermediate qqq:
,{$project: { qqq:
{$arrayElemAt: [
{ $filter: {
input: "$stations",
as: "z",
cond: { $eq: [ "$$z.stationName", "livingroom" ] }
}}, 0]
}
}}
// Lastly, just project measures and not _id from this object:
,{$project: { _id:0, measures: "$qqq.measures" }}
]);
那么您只想要至少存在一个度量值的站点?不,我只想要度量值数组的内容,来自我在查询中查找的站点:const query={apiKey:user.apiKey,'stations.stationName':req.params.stationName}它应该只返回“livingroom”的度量值,但它也显示了电台“办公室”,正如你在上面的结果中所看到的。有什么想法吗?谢谢你的回答!我会试试这个,但它仍然不会只选择和返回度量值数组,对吗?是的,试试看!根据您对该问题的评论,它将返回所请求的stationName的度量值(预期结果)。这是第一个实际使用本机mongoose函数的答案。你能告诉我为什么在我做的例子中投影不起作用吗?您的方法工作得更好,因为它只返回所需的数据,但我上面的问题是,它还返回站点dat的度量值数组,而在de查询中,该数组与de station name不匹配。再次感谢!