代码之家  ›  专栏  ›  技术社区  ›  Ben Noland

获取最近的姓名、分数

  •  2
  • Ben Noland  · 技术社区  · 15 年前

    我有一个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'})
    

    {name: "John", value: 97.3}
    {name: "Bob", value: 96.3}
    
    1 回复  |  直到 15 年前
        1
  •  5
  •   Niels van der Rest    15 年前

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

    映射

    GROUP BY SQL中的子句。在您的情况下,我们将按名称分组,因此我们将使用名称作为 key . 这个 value 将包含我们需要的其他数据,在本例中是值和时间戳。

    map = function () {
      emit(this.name, { timeStamp: this.timeStamp, value: this.value });
    }
    

    map函数将为每个键生成一个值数组。因此,所有名为“Bob”的文档都映射到键“Bob”。对于示例数据,结果可能如下所示:

    { _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;
    }
    

    { _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:

    res = db.scores.mapReduce(map, reduce, { finalize: finalize });
    

    收藏 db[res.result] 将包含查询结果。

    最后一个问题

    Date objects . 根据示例代码判断,时间戳存储为字符串,而不是日期对象或整数时间戳。因此,在比较日期之前,必须将这些字符串转换为日期对象。