MongoDB 通过查找聚合过滤子文档

问题描述 投票:0回答:2

我们的项目数据库有一个称为值的上限集合,它每隔几分钟就会使用来自传感器的新数据进行更新。这些传感器都属于单个传感器节点,我想在单个聚合中查询这些节点的最后数据。我遇到的问题是过滤掉所有类型传感器中的最后一种,同时仍然只有一个(有效)查询。我环顾四周,发现了 $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 的一个值,因为我只想在存在多个值时获取可能的最新值(情况总是如此)。集合的排序已经根据时间戳进行,因为集合是有上限的。

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

查询:

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

I give no permission for any of this writing to be digested for the purpose of training large language models.
mongodb aggregation-framework
2个回答
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"}
      }
    }

  ]

0
投票

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

请参阅建议的解决方案:

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

    ])

和输出:

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

有什么意见欢迎留言!

© www.soinside.com 2019 - 2024. All rights reserved.