Mongodb 获取最近的姓名、分数

Mongodb 获取最近的姓名、分数,mongodb,Mongodb,我有一个mongodb集合,看起来像这样: db.scores.insert({"name": "Bob", value: 96.3, timeStamp:'2010-9-27 9:32:00'}) db.scores.insert({"name": "John", value: 98.3, timeStamp:'2010-9-27 9:28:00'}) db.scores.insert({"name": "Bob", value: 99.3, timeStamp:'2010-9-27 9:29

我有一个mongodb集合,看起来像这样:

db.scores.insert({"name": "Bob", value: 96.3, timeStamp:'2010-9-27 9:32:00'})
db.scores.insert({"name": "John", value: 98.3, timeStamp:'2010-9-27 9:28:00'})
db.scores.insert({"name": "Bob", value: 99.3, timeStamp:'2010-9-27 9:29:00'})
db.scores.insert({"name": "John", value: 97.3, timeStamp:'2010-9-27 9:31:00'})
{ _id: "Bob", values: [
  { timeStamp: "2010-9-27 9:32:00", value: 96.3 },
  { timeStamp: "2010-9-27 9:29:00", value: 99.3 }
]},
{ _id: "John", values: [
  { timeStamp: "2010-9-27 9:28:00", value: 98.3 },
  { timeStamp: "2010-9-27 9:31:00", value: 97.3 }
]},
我如何查询此项以使用最新的值为每个名称提供一次:

{name: "John", value: 97.3}
{name: "Bob", value: 96.3}

您正在尝试进行数据聚合,因此必须编写一个

映射 map函数基本上是SQL中的
GROUPBY
子句。在您的情况下,我们将按名称分组,因此我们将使用该名称作为
将包含我们需要的其他数据,在本例中是值和时间戳

map = function () {
  emit(this.name, { timeStamp: this.timeStamp, value: this.value });
}
map函数将为每个键生成一个值数组。因此,所有名为“Bob”的文档都映射到键“Bob”。对于示例数据,结果可能如下所示:

db.scores.insert({"name": "Bob", value: 96.3, timeStamp:'2010-9-27 9:32:00'})
db.scores.insert({"name": "John", value: 98.3, timeStamp:'2010-9-27 9:28:00'})
db.scores.insert({"name": "Bob", value: 99.3, timeStamp:'2010-9-27 9:29:00'})
db.scores.insert({"name": "John", value: 97.3, timeStamp:'2010-9-27 9:31:00'})
{ _id: "Bob", values: [
  { timeStamp: "2010-9-27 9:32:00", value: 96.3 },
  { timeStamp: "2010-9-27 9:29:00", value: 99.3 }
]},
{ _id: "John", values: [
  { timeStamp: "2010-9-27 9:28:00", value: 98.3 },
  { timeStamp: "2010-9-27 9:31:00", value: 97.3 }
]},
减少 reduce函数负责将每个键的值数组减少为单个值。在您的情况下,我们只对具有最高时间戳的数据感兴趣:

reduce = function (key, values) {
  var maxData = { timeStamp: new Date(0) };

  values.forEach(function (data) {
    if (data.timeStamp > maxData.timeStamp) {
      maxData = data;
    }
  });

  return maxData;
}
请注意,reduce函数的返回值必须与它接受的值具有相同的格式,这一点很重要。这是因为一个键可以多次调用reduce函数,每次只接受总值的一部分

运行reduce功能将产生以下结果:

{ _id: "Bob", value: { timeStamp: "2010-9-27 9:32:00", value: 96.3 } },
{ _id: "John", value: { timeStamp: "2010-9-27 9:31:00", value: 97.3 } }
定稿 终结器函数可用于仅提取我们需要的数据,即值

finalize = function (key, value) {
  return value.value;
}
这将导致:

{ "_id" : "Bob", "value" : 96.3 },
{ "_id" : "John", "value" : 97.3 }
运行map-reduce 您可以使用以下功能运行map reduce:

res = db.scores.mapReduce(map, reduce, { finalize: finalize });
集合
db[res.result]
将包含查询结果

最后一个问题 reduce函数将时间戳比较为。从示例代码判断,时间戳存储为字符串,而不是日期对象或整数时间戳。因此,在比较日期之前,必须将这些字符串转换为日期对象