【问题标题】:MongoDB Aggregation - Group by, Select additional fields in resultMongoDB 聚合 - 分组方式,在结果中选择其他字段
【发布时间】:2016-08-30 01:47:57
【问题描述】:

我一直在尝试使用 MongoDB 聚合运算符来获取最后一条记录(基于“fixtm”,即 fixtime)。每条记录都有一个设备 ID、固定时间和一些其他信息,如纬度、经度、速度等。我的以下聚合工作正常,它返回每个设备的最后一条记录。但是我如何获得纬度、经度等其他字段?我尝试在 $project 列表中添加 lat: 1 之类的内容,但无论我尝试了多少变化,其他值都不会显示。我认为这是因为它们不存在于组运营商的 _id 字段或其他什么?任何指针都会有很大帮助。谢谢

function() {
    return db.gpspos.aggregate(
        [
            {
                $sort: {
                    devid: 1,
                    fixtm: 1
                }
            }, {
                $group: {
                    _id: "$devid",
                    lastData: {
                        $last: "$fixtm"
                    }
                }
            }, {
                $project: {
                    _id: 0,
                    device_id: '$_id',
                    fixtime: '$lastData'
                }
            }
        ]
    )
}

我从上面得到的是

{ "device_id" : 5, "fixtime" : 1462368405000 }
{ "device_id" : 4, "fixtime" : 1462372097000 }

我看到的是这个

{ "device_id" : 5, "fixtime" : 1462368405000, "speed": 70.3, "lat": 103.33434 }
{ "device_id" : 4, "fixtime" : 1462372097000, "speed": 70.3, "lat": 101.33434 }

我的 MongoDB 中的文档示例

{
    "_id": {
        "$oid": "5729dc83f5be2411fb28c7c3"
    },
    "devid": 5,
    "devnm": "M.M (Samsung S3)",
    "fixtm": 1462360893000,
    "addr": "{address}",
    "lat": 1.433775,
    "lon": 103.7859717,
    "spdkm": 0
}

【问题讨论】:

  • 您能否编辑您的问题以包含您在上述结果中获得的一些示例文档?
  • 当然,完成

标签: mongodb aggregation-framework


【解决方案1】:

要同时返回其他字段,您可以在 $group 操作中使用相同的 $last 运算符。这将返回每个组的最后一个文档中的相应字段:

function() {
    return db.gpspos.aggregate(
        [
            {
                $sort: {
                    devid: 1,
                    fixtm: 1
                }
            }, {
                $group: {
                    _id: "$devid",
                    lastData: { $last: "$fixtm" },
                    speed: { $last: "$spdkm" },
                    address: { $last: "$address" },
                    lat: { $last: "$lat" },
                    lon: { $last: "$lon" }
                }
            }, {
                $project: {
                    _id: 0,
                    device_id: '$_id',
                    fixtime: '$lastData',
                    speed: 1,
                    address: 1,
                    lat: 1,
                    lon: 1
                }
            }
        ]
    )
}

【讨论】:

  • 哦,所以即使我需要的是基于 fixtm(unix 时间)的最后一条记录,我也必须在其他字段上使用 $last 累加器?所以我猜它首先找到 fixtm 的最后一条记录,然后是其余的 - 所以它不会影响返回的内容?这是逻辑吗?
  • 想想 Linux 的“管道”上下文中的聚合管道;执行管道时,MongoDB 将运算符相互连接,即一个运算符的输出成为下一个运算符的输入。每个运算符的结果是一个新的文档集合。因此,当您想在最终管道阶段返回字段时,它们应该来自前一个运算符,在这种情况下,其他字段应该来自 $group 管道。就像在 SQL 中一样,除非您使用任何聚合函数,否则您不能使用 GROUP BY。在 MongoDB 中,您必须使用 $last 或 $first`
  • 好的,我有点明白了,但只是简单的说明 - 如果我需要包含一个非数字字段怎么办。例如说地址(地址)。 $last 将如何反对这一点?对不起,我对 MongoDB 完全陌生,所以试着慢慢消化东西:)
  • $last 总是从每个组的最后一个文档中返回一个值,它可以是任何值(字符串、数字等)
  • 如果您有任何其他推荐的方式也可以。基本上我想要的只是每个设备的最后一条记录。用另一种方式描述它:假设我有 5 台设备的 50 条记录。我需要的是每个设备的最后插入记录(fixtm),这意味着我的结果将显示 5 条记录(基于最后一个 fixtim)
猜你喜欢
  • 1970-01-01
  • 2017-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-19
  • 2014-02-27
  • 1970-01-01
相关资源
最近更新 更多