Mongodb聚合与猫鼬过滤器嵌入式文档

时间:2019-05-03 14:38:11

标签: mongodb mongoose

我正在使用NodeJS和mongoose,并汇总了两个集合:

集合1(工作站)

/* 1 */
{
    "_id" : ObjectId("xxx"),
    "marca" : "x",
    "modelo" : "xx",
    "fabricante" : "x",
    "id_station" : [ 
        191, 
        457
    ],
    "sensor_type" : [ 
        {
            "name" : 2,
            "type" : "clima",
            "place" : "interior",
            "img" : "assets/img/hum.png",
            "name_comun" : "Hum. Relativa",
            "medida" : "%",
            "interfaz" : ""
        }, 
        {
            "name" : 3,
            "type" : "clima",
            "place" : "interior",
            "img" : "assets/img/hum.png",
            "name_comun" : "Hum. Relativa",
            "medida" : "%",
            "interfaz" : ""
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5ccacc61a0160f16c50f5a1b"),
    "marca" : "y",
    "modelo" : "yy",
    "fabricante" : "y",
    "id_station" : [ 
        999
    ],
    "sensor_type" : [ 
        {
            "name" : 2,
            "type" : "clima",
            "place" : "interior",
            "img" : "assets/img/hum.png",
            "name_comun" : "Temperatura",
            "medida" : "%",
            "interfaz" : ""
        }, 
        {
            "name" : 3,
            "type" : "clima",
            "place" : "interior",
            "img" : "assets/img/hum.png",
            "name_comun" : "Hum. Relativa",
            "medida" : "%",
            "interfaz" : ""
        }
    ]
}

集合2(度量):

/* 1 */
{
    "_id" : ObjectId("5ccc29612bda12f1f16ac600"),
    "id_station" : "191",
    "attrName" : 2,
    "attrType" : "float",
    "attrValue" : 21,
    "recvTimeTs" : 1554134471,
    "recvTime" : "2019-04-01T16:01:11.000Z"
}

/* 2 */
{
    "_id" : ObjectId("5ccc2a852bda12f1f16ac6b1"),
    "id_station" : "191",
    "attrName" : 3,
    "attrType" : "float",
    "attrValue" : 2222,
    "recvTimeTs" : 1554134499,
    "recvTime" : "2019-09-01T16:01:11.000Z"
}

/* 3 */
{
    "_id" : ObjectId("5ccc3a7d2bda12f1f16acc34"),
    "id_station" : "999",
    "attrName" : 33,
    "attrType" : "float",
    "attrValue" : 2222,
    "recvTimeTs" : 1554134499,
    "recvTime" : "2019-09-01T16:01:11.000Z"
}

完成聚合后,将显示完全嵌入到集合中的文档,而我只需要显示与attrname匹配的文档即可。

如何在嵌入式文档中执行搜索?是否可以仅显示该信息?

我需要sensor_type仅显示名称信息:33,因为当嵌入式文档显示该数据并且是错误的时,它是2的真实值。

有错误的代码:

    {
   "DatagreenhouseRecuperado":[
      {
         "_id":33,
         "medidas":[
            {
               "_id":"5ccacc61a0160f16c50f5a1b",
               "marca":"Metos",
               "modelo":"Estacion",
               "fabricante":"Metos",
               "id_station":[
                  999
               ],
               "sensor_type":[
                  {
                     "name":2,
                     "type":"clima",
                     "place":"interior",
                     "img":"assets/img/hum.png",
                     "name_comun":"Temperatura",
                     "medida":"%",
                     "interfaz":""
                  },
                  {
                     "name":33,
                     "type":"clima",
                     "place":"interior",
                     "img":"assets/img/hum.png",
                     "name_comun":"Hum. Relativa",
                     "medida":"%",
                     "interfaz":""
                  }
               ],
               "attrName":33,
               "attrValue":8888,
               "recvTimeTs":1588524826,
               "recvTime":"2020-05-03T18:53:46"
            }
         ],
         "count":1
      }
   ]
}

目标是:

{
   "DatagreenhouseRecuperado":[
      {
         "_id":33,
         "medidas":[
            {
               "_id":"5ccacc61a0160f16c50f5a1b",
               "marca":"Metos",
               "modelo":"Estacion",
               "fabricante":"Metos",
               "id_station":[
                  999
               ],
               "sensor_type":[
                  {
                     "name":33,
                     "type":"clima",
                     "place":"interior",
                     "img":"assets/img/hum.png",
                     "name_comun":"Hum. Relativa",
                     "medida":"%",
                     "interfaz":""
                  }
               ],
               "attrName":33,
               "attrValue":8888,
               "recvTimeTs":1588524826,
               "recvTime":"2020-05-03T18:53:46"
            }
         ],
         "count":1
      }
   ]
}

代码:

     function getDataSensorGreenhouseLastDataPruebas(req, res) {
        var array = req.params.nombresensores;
        var id_station = array.split(',');
        var array2 = req.params.sensores;
        //var sensor = array2.split(',');
        // var id_station = req.params.id_station;
        console.log('id_station: ' + id_station);
        Datagreenhouse.aggregate([
            { "$match": { "id_station": { "$in": [191, 999] }, "attrName": { "$in": [2, 33] } } },
            { "$sort": { "recvTime": -1 } },
            {
                "$group": {
                    "_id": "$id_station",
                    "latest": { "$first": "$$ROOT" },
                }
            },
            {
                "$project": {
                    "_id": 1,
                    "id_station": "$latest.id_station",
                    "attrName": "$latest.attrName",
                    "attrValue": "$latest.attrValue",
                    "recvTimeTs": "$latest.recvTimeTs",
                    "recvTime": "$latest.recvTime"
                }
            },
            {
                "$lookup": {
                    "from": "station_types",
                    "localField": "id_station", // local field in measurements collection
                    "foreignField": "id_station", //foreign field from sensors collection
                    "as": "sensor"
                }
            },
            { "$unwind": "$sensor" },
            // { "$match": { "sensor.sensor_type.name": 2 } },
            {
                "$addFields": {
                    "sensor.attrName": "$attrName", // Add attrName to the sensors
                    "sensor.attrValue": "$attrValue", // Add attrValue to the sensors
                    "sensor.recvTimeTs": "$recvTimeTs",
                    "sensor.recvTime": "$recvTime"

                }
            },
            {
                "$group": {
                    "_id": "$id_station", // Group by time
                    "medidas": { "$push": "$sensor" }, // Collect measurements
                    "count": { "$sum": 1 } // Count measurements
                }
            },

        ], (err, DatagreenhouseRecuperado) => {
            if (err) return res.status(500).send({ message: 'Error al realizar la peticion' + err })
            if (!DatagreenhouseRecuperado) return res.status(404).send({ message: 'Error el usuario no existe' })
            console.log('Ordenado: ' + JSON.stringify(DatagreenhouseRecuperado));

            /*DatagreenhouseRecuperado.sort(function(a, b) {
                return (a._id - b._id)
            })*/
            res.status(200).send({ DatagreenhouseRecuperado })
        })
    }

问候,谢谢。

EDIT 01 解决方案

您好,这是对代码的改编:

{
        "$addFields": {
            "sensor.attrValue": "$attrValue", // Add attrValue to the sensors
            "sensor.attrName": "$attrName", // Add attrValue to the sensors
            "sensor.recvTimeTs": "$recvTimeTs", // Add attrName to the sensors
            "sensor.pruebas": "$name_comun", // Add attrName to the sensors
            "sensor.sensor_type": {
                $filter: {
                    input: '$sensor.sensor_type',
                    as: 'shape',
                    cond: { $eq: ['$$shape.name', '$attrName'] },
                }
            }
        }
    },

问题在于在sensor_type中它显示数据,而不是该对象的所有信息。如何添加其他字段?

1 个答案:

答案 0 :(得分:0)

基本上,所有代码都是正确的,您在该查找中所做的与所有传感器匹配,sensor_types数组内部具有一个名称为“ XX”的传感器。查找完成了它的工作,它返回所有匹配项,但是这些数组还有其他文档。当您匹配子文档时,它不会为您过滤。

只需在$ project中过滤它们,或在$ addFields中添加以下内容

"sensor.sensor_type": {
    "$filter": {
        "input": "$sensor.sensor_type",
        "as": "sensorType",
        "cond": { "$eq": ['$$sensorType.name', 33]}
    }
 }

您可以做的另一件事是更改$ lookup以使let和管道在该管道内进行匹配并投影数据。这是一种更干净,更好的方法。当天晚些时候,我还将通过此示例更新答案。