MongoDB使用查找聚合

时间:2016-05-04 11:38:10

标签: mongodb aggregation-framework

我们的项目数据库有一个称为值的上限集合,每隔几分钟就会使用来自传感器的新数据进行更新。这些传感器都属于单个传感器节点,我想在单个聚合中查询这些节点的最后数据。我遇到的问题是过滤掉所有类型的传感器中的最后一个,同时仍然只有一个(有效的)查询。我环顾四周,找到了$ group参数,但在这种情况下,我似乎无法弄清楚如何正确使用它。

数据库结构如下:

节点:

{
    "_id": 681
    "sensors": [
            {
                "type": "foo"
            },
            {
                "type": "bar"
            }
    ]
}

值:

{
    "_id" : ObjectId("570cc8b6ac55850d5740784e"),
    "timestamp" : ISODate("2016-04-12T12:06:46.344Z"),
    "type" : "foo",
    "nodeid" : 681,
    "value" : 10
}

{
    "_id" : ObjectId("190ac8b6ac55850d5740776e"),
    "timestamp" : ISODate("2016-04-12T12:06:46.344Z"),
    "type" : "bar",
    "nodeid" : 681,
    "value" : 20
}

{
    "_id" : ObjectId("167bc997bb66750d5740665e"),
    "timestamp" : ISODate("2016-04-12T12:06:46.344Z"),
    "type" : "bar",
    "nodeid" : 200,
    "value" : 20
}

{
    "_id" : ObjectId("110cc9c6ac55850d5740784e"),
    "timestamp" : ISODate("2016-04-09T12:06:46.344Z"),
    "type" : "foo",
    "nodeid" : 681,
    "value" : 12
}

所以让我们想象我想要节点681的数据,我想要一个像这样的结构:

节点:

{
    "_id": 681
    "sensors": [
            {
                "_id" : ObjectId("570cc8b6ac55850d5740784e"),
                "timestamp" : ISODate("2016-04-12T12:06:46.344Z"),
                "type" : "foo",
                "nodeid" : 681,
                "value" : 10
            },
            {
                "_id" : ObjectId("190ac8b6ac55850d5740776e"),
                "timestamp" : ISODate("2016-04-12T12:06:46.344Z"),
                "type" : "bar",
                "nodeid" : 681,
                "value" : 20
            }
    ]
}

注意如何查询foo的一个值,因为如果有多个值(总是如此),我想只获取最新的值。集合的顺序已经根据时间戳排列,因为集合有上限。

我有这个查询,但它只是获取数据库中的所有值(这在一生中是太多了,更不用说Web应用程序的一个请求了),所以我想知道如何过滤它之前聚合。

查询:

db.nodes.aggregate(
        [
            {
                $unwind: "$sensors"
            }, 
            {
                $match:{
                    nodeid: 681
                       }
            }, 
            {
                $lookup:{
                        from: "values", localField: "sensors.type", foreignField: "type", as: "sensors"
                    }
             }
         }
    ]
)

2 个答案:

答案 0 :(得分:1)

试试这个

  // Pipeline
  [
    // Stage 1 - sort the data collection if not already done (optional)
    {
      $sort: {
       "timestamp":1
      }
    },

    // Stage 2 - group by type & nodeid then get first item found in each group
    {
      $group: {
        "_id":{type:"$type",nodeid:"$nodeid"},
        "sensors": {"$first":"$$CURRENT"}  //consider using $last if your collection is on reverse
      }
    },

    // Stage 3 - project the fields in desired
    {
      $project: {
       "_id":"$sensors._id",
       "timestamp":"$sensors.timestamp",
       "type":"$sensors.type",
       "nodeid":"$sensors.nodeid",
       "value":"$sensors.value"
      }

    },

    // Stage 4 - group and push it to array sensors
    {
      $group: {
        "_id":{nodeid:"$nodeid"},
        "sensors": {"$addToSet":"$$CURRENT"}
      }
    }

  ]

答案 1 :(得分:0)

就我的文档结构而言,没有必要使用$ lookup,因为所有数据都在读数(值)集合中。

请参阅建议的解决方案:

Iterator
  

并输出:

db.readings.aggregate([{
            $match : {
                nodeid : 681
            }
        },
        {
            $group : {
                _id : {
                    type : "$type",
                    nodeid : "$nodeid"
                },
                readings : {
                    $push : {
                        timestamp : "$timestamp",
                        value : "$value",
                        id : "$_id"
                    }
                }
            }
        }, {
            $project : {
                _id : "$_id",
                readings : {
                    $slice : ["$readings", -1]
                }
            }
        }, {
            $unwind : "$readings"
        }, {
            $project : {
                _id : "$readings.id",
                type : "$_id.type",
                nodeid : "$_id.nodeid",
                timestamp : "$readings.timestamp",
                value : "$readings.value",

            }
        }, {
            $group : {
                _id : "$nodeid",
                sensors : {
                    $push : {
                        _id : "$_id",
                        timestamp : "$timestamp",
                        value : "$value",
                        type:"$type"
                    }
                }
            }
        }

    ])

欢迎任何评论!