首先,我有两个集合,users
和sensors
。用户看起来像:
{
"_id" : ObjectId("5d471ec414197a868de1b533"),
"email" : "example_email@hotmail.co.uk",
"hashedPassword" : "hash",
"confirmation_code" : "conf",
"confirmed" : true,
"sensors" : [
"asde22re",
]
}
传感器看起来像:
"_id" : ObjectId("5d4c85d7b032b64f1c1a0b14"),
"sensorId" : "asde22re",
"data" : [
{
"data" : "10343",
"time" : "2019-08-08T20:28:07.241Z"
},
{
"data" : "11002",
"time" : "2019-08-08T20:28:26.594Z"
}
]
我有一个端点GET /sensors
,它应该返回用户也可以访问的所有传感器的数据,这可以在users.sensors
中找到。
我不确定如何实际谷歌我想要什么(可能是我的无知(,但本质上我需要一个查询,给定users.email
它返回相应用户也可以访问的所有传感器。
我可以做到这一点的一种方法是:
dbo.collection('users').findOne({ email: 'example_email' })
然后使用此响应,获取users.sensors
并对集合中的每个传感器进行foreach
,但这似乎效率低下。
如何将其合并到一个查询中?
编辑: 如果有帮助,这就是我试图复制的
dbo.collection('users').findOne({ email }, { fields: { sensors: 1, _id: 0 } }, (err, results) => {
if(err){
return res.json({ err });
}
const { sensors } = results;
dbo.collection('sensors').find({ sensorId: { $in: [sensors] } }).toArray((err, results) => {
if(err){
return res.json({ err });
}
return res.json({ results });
});
});
类似于sql中的"joins",在Mongo中你必须使用"lookup"。
要使用查找,您必须使用"聚合"查询,
所以你需要的查询是,
db.collection('users').aggregate({$match:{ email: 'example_email' }},
{$unwind:{path:"$sensors"}},
{$lookup:{from:"sensor", localField: "sensors", foreignField:"sensorId", as:"sensorDetails"}},
(err, userData)=>{
console.log(userData);
})
那么这个查询在做什么,
请参阅"用户"集合中的"$lookup"行--->,它使用"传感器"字段(用户集合的本地字段,如SQL中的主ID(并从与sensorId匹配的"传感器"集合中获取信息(传感器集合中的外部字段(,并将结果存储在"sensorDetails"字段中。
您可以使用"userData[0].sensorDetails"访问sensorDetails。 传感器详细信息将是数组。
查看有关查找的官方文档 另请阅读有关放松的信息
请尝试以下操作:
dbo.collection('users').aggregate([{ $match: { email: 'example_email@hotmail.co.uk' } }, { $unwind: "$sensors" },
{
$lookup:
{
from: "sensors",
localField: "sensors",
foreignField: "sensorId",
as: "sensorDetails"
}
}, {
$group: { _id: '$_id', "userDetails": { "$first": "$$ROOT" }, "sensors": { "$push": "$sensors" }, "sensorDetails": { "$push": { "$arrayElemAt": ["$sensorDetails", 0] } } }
},
{ $addFields: { 'userDetails.sensors': '$sensors', 'userDetails.sensorDetails': '$sensorDetails' } },
{
$replaceRoot: { "newRoot": "$userDetails" }
}])
使用mongoDB v3.4 或更高版本,您只需使用$lookup
即可达到预期的结果,这里您不需要在localField上使用$unwind
即使是数组,也不再重要:
dbo.collection('users').aggregate([{ $match: { email: 'example_email@hotmail.co.uk' } },
{
$lookup:
{
from: "sensors",
localField: "sensors",
foreignField: "sensorId",
as: "sensorDetails"
}
}])