【问题标题】:Using $last on Mongo Aggregation Pipeline在 Mongo 聚合管道上使用 $last
【发布时间】:2016-04-26 10:31:13
【问题描述】:

我搜索了类似的问题,但找不到任何问题。请随时为我指明他们的方向。

假设我有这些数据:

{ "_id" : ObjectId("5694c9eed4c65e923780f28e"), "name" : "foo1", "attr" : "foo" }
{ "_id" : ObjectId("5694ca3ad4c65e923780f290"), "name" : "foo2", "attr" : "foo" }
{ "_id" : ObjectId("5694ca47d4c65e923780f294"), "name" : "bar1", "attr" : "bar" }
{ "_id" : ObjectId("5694ca53d4c65e923780f296"), "name" : "bar2", "attr" : "bar" }

如果我想获取每个属性组的最新记录,我可以这样做:

> db.content.aggregate({$group: {_id: '$attr', name: {$last: '$name'}}})
{ "_id" : "bar", "name" : "bar2" }
{ "_id" : "foo", "name" : "foo2" }

我想让我的数据按attr 分组,然后按_id 排序,这样每个组中只保留最新的记录,这就是我可以实现的方法。但是我需要一种方法来避免在结果中命名我想要的所有字段(在本例中为“名称”),因为在我的实际用例中,它们事先并不知道。

那么,有没有办法实现这一点,但不必使用$last 显式命名每个字段而只取所有字段?当然,我会在分组之前对数据进行排序,我只需要以某种方式告诉 Mongo“从最新的值中获取所有值”。

【问题讨论】:

  • 事先不知道的字段名是 MongoDB 中的一种反模式,会导致各种无法解决的问题,应尽可能避免。
  • 它们并不完全是任意的,只是我有一个可以属于两个类别之一的项目集合。就像一个包含卡车和汽车的“车辆”集合。我是否应该重新组织它,使集合中所有记录的所有字段都完全相同?
  • MongoDB 的无模式特性允许您拥有仅存在于特定类型文档中的“可选”字段,但是当您拥有在不同类型中表示相同事物的字段时,它们应该具有相同的名称.否则你会遇到这个(以及许多其他)问题。
  • 不,没有在不同类型中表示相同含义的字段。我的两种类型的项目在 70% 的属性中重叠,其余的都是可选的并且特定于每种类型。但我想避免在我的服务中对属性名称进行逻辑和硬编码。如果可能的话,我想接受“所有的一切”。

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

查看一些可能的选项here:

  • 对您的每个 attr 值执行多个 find().sort() 查询 想要搜索。
  • 获取 $last doc 的原始 _id,然后为每个值执行 findOne()(这是更可扩展的选项)。
  • 使用$$ROOT 系统变量,如here 所示。

这不是最快的操作,但我假设您更多地将其用于分析,而不是响应用户行为。

编辑添加了 slouc 在 cmets 中发布的示例: db.content.aggregate({$group: {_id: '$attr', lastItem: { $last: "$$ROOT" }}}).

【讨论】:

  • 我不知道 $$ROOT,这对我有帮助。其他示例:db.content.aggregate({$group: {_id: '$attr', lastItem: { $last: "$$ROOT" }}})。请注意,如果您使用的是 ReactiveMongo(就像我一样),您只需要使用一个美元符号。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-09
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-11
  • 1970-01-01
相关资源
最近更新 更多