Node.js MongoDB正在寻找一种基于另一个集合的集合从另一个集合返回文档的方法

Node.js MongoDB正在寻找一种基于另一个集合的集合从另一个集合返回文档的方法,node.js,mongodb,Node.js,Mongodb,首先,我有两个集合,用户和传感器。用户看起来像: { "_id" : ObjectId("5d471ec414197a868de1b533"), "email" : "example_email@hotmail.co.uk", "hashedPassword" : "hash", "confirmation_code" : "conf", "confirmed" : true, "sensors" : [ "asde22re",

首先,我有两个集合,
用户
传感器
。用户看起来像:

{
    "_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"
        }
    ]
传感器看起来像:

{
    "_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
中找到

我不确定如何用谷歌搜索我想要的东西(可能我自己不知道),但本质上我需要一个查询,在给定
用户的地方。电子邮件
也会返回相应用户可以访问的所有传感器

我可以这样做的一个方法就是:

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中的“连接”类似,在Mongo中必须使用“查找”

要使用查找,必须使用“聚合”查询

所以你需要的是

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);
})
那么这个查询在做什么

请参阅“users”集合中的“$lookup”行--->它使用“sensors”字段(用户集合的本地字段,如sql中的主id),并从“sensor”集合中获取与sensorId匹配的信息(传感器集合中的外部字段),并将结果存储在“sensorDetails”字段中

您可以通过“userData[0].sensorDetails”访问sensorDetails。 传感器详细信息将显示在阵列中

查阅官方文件 另外,请阅读与sql中的“连接”类似的内容,在Mongo中,您必须使用“查找”

要使用查找,必须使用“聚合”查询

所以你需要的是

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);
})
那么这个查询在做什么

请参阅“users”集合中的“$lookup”行--->它使用“sensors”字段(用户集合的本地字段,如sql中的主id),并从“sensor”集合中获取与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"
    }
}])
请试试这个:

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"
    }
}])

谢谢你的评论。我不能让它正常工作,所以我把它改为:adbo.collection('users').aggregate({$match:{email}},{$lookup:{from:'sensor',localField:'sensors',foreignField:'sensorId',as:'sensorDetails'}})。这与
sensors
字段是一个数组这一事实有关吗?是的。。集合({$match:{email}},{$lookup:{from:'sensor',localField:'sensors',foreignField:'sensorId',as:'sensorDetails'})。聚合({$match:{email}},{$lookup:{from:'sensor',as:'sensorDetails'})。toArray((err res=>{console.log(err res);})这将。。这和阵列中的“传感器”字段没有任何关系。好吧,这似乎没有给我返回任何东西。它返回的是实际用户,没有传感器信息。我还将
从:'sensors
更改为
从:'sensors'
,这也不起作用。不,我错过了“unwind”管道。。好了,现在试试这个。“$lookup”中的“from”字段表示我们正在执行查找的第二个集合的名称,而不是字段名称,“foreignField”表示我们必须用于匹配的第二个集合的字段。感谢您的评论。我不能让它正常工作,所以我把它改为:adbo.collection('users').aggregate({$match:{email}},{$lookup:{from:'sensor',localField:'sensors',foreignField:'sensorId',as:'sensorDetails'}})。这与
sensors
字段是一个数组这一事实有关吗?是的。。集合({$match:{email}},{$lookup:{from:'sensor',localField:'sensors',foreignField:'sensorId',as:'sensorDetails'})。聚合({$match:{email}},{$lookup:{from:'sensor',as:'sensorDetails'})。toArray((err res=>{console.log(err res);})这将。。这和阵列中的“传感器”字段没有任何关系。好吧,这似乎没有给我返回任何东西。它返回的是实际用户,没有传感器信息。我还将
从:'sensors
更改为
从:'sensors'
,这也不起作用。不,我错过了“unwind”管道。。好了,现在试试这个。“$lookup”中的“from”字段表示我们正在执行查找的第二个集合的名称,而不是字段名称,“foreignField”表示我们必须用于匹配的第二个集合中的字段。