【问题标题】:MongoDB MapReduce producing different results for each documentMongoDB MapReduce 为每个文档产生不同的结果
【发布时间】:2013-05-24 12:33:46
【问题描述】:

这是this question 的后续,我尝试用聚合框架解决这个问题。不幸的是,我必须等待才能将这个特定的 mongodb 安装更新到包含聚合框架的版本,所以不得不使用 MapReduce 来完成这个相当简单的数据透视操作。

我输入了以下格式的数据,每天都有多个转储:

"_id" : "daily_dump_2013-05-23",
    "authors_who_sold_books" : [
        {
            "id" : "Charles Dickens",
            "original_stock" : 253,
            "customers" : [
                {
                   "time_bought" : 1368627290,
                   "customer_id" : 9715923
                }
            ]
        },
        {
            "id" : "JRR Tolkien",
            "original_stock" : 24,
            "customers" : [
                {
                    "date_bought" : 1368540890,
                    "customer_id" : 9872345
                },
                {
                    "date_bought" : 1368537290,
                    "customer_id" : 9163893
                }
            ]
        }
    ]
}

我追求以下格式的输出,该格式汇总了所有每日转储中每个(唯一)作者的所有实例:

{
    "_id" : "Charles Dickens",
    "original_stock" : 253,
    "customers" : [
        {
            "date_bought" : 1368627290,
            "customer_id" : 9715923
        },
        {
            "date_bought" : 1368622358,
            "customer_id" : 9876234
        },
        etc...
    ]
}

这个地图函数我已经写好了……

function map() {
  for (var i in this.authors_who_sold_books)
  {
    author = this.authors_who_sold_books[i];
    emit(author.id, {customers: author.customers, original_stock: author.original_stock, num_sold: 1});
  }
}

...还有这个reduce函数。

function reduce(key, values) {
  sum = 0
  for (i in values)
  {
    sum += values[i].customers.length
  }
  return {num_sold : sum};
}

但是,这给了我以下输出:

{
  "_id" : "Charles Dickens",
  "value" : {
    "customers" : [
      {
        "date_bought" : 1368627290,
        "customer_id" : 9715923
      },
      {
        "date_bought" : 1368622358,
        "customer_id" : 9876234
      },
    ],
    "original_stock" : 253,
    "num_sold" : 1
  }
}
{ "_id" : "JRR Tolkien", "value" : { "num_sold" : 3 } }
{
  "_id" : "JK Rowling",
  "value" : {
    "customers" : [
      {
        "date_bought" : 1368627290,
        "customer_id" : 9715923
      },
      {
        "date_bought" : 1368622358,
        "customer_id" : 9876234
      },
    ],
    "original_stock" : 183,
    "num_sold" : 1
  }
}
{ "_id" : "John Grisham", "value" : { "num_sold" : 2 } }

偶数索引文档列出了客户和 original_stock,但 num_sold 的总和不正确。 奇数索引文档只列出了 num_sold,但它是正确的数字。

谁能告诉我我错过了什么?

【问题讨论】:

    标签: mongodb mapreduce


    【解决方案1】:

    您的问题是由于 reduce 函数的输出格式应该与 map 函数的格式相同(有关说明,请参阅 requirements for the reduce function)。

    您需要将代码更改为以下内容以解决问题,:

    function map() {
      for (var i in this.authors_who_sold_books)
      {
        author = this.authors_who_sold_books[i];
        emit(author.id, {customers: author.customers, original_stock: author.original_stock, num_sold: author.customers.length});
      }
    }
    
    function reduce(key, values) {
      var result = {customers:[] , num_sold:0, original_stock: (values.length ? values[0].original_stock : 0)};
      for (i in values)
      {
        result.num_sold += values[i].num_sold;
        result.customers = result.customers.concat(values[i].customers);
      }
      return result;
    }
    

    希望对你有帮助。

    注意:地图函数中num_sold: author.customers.length 的变化。我想这就是你想要的

    【讨论】:

      猜你喜欢
      • 2020-05-08
      • 1970-01-01
      • 2017-06-29
      • 2014-07-18
      • 1970-01-01
      • 2018-05-23
      • 2017-09-11
      • 2020-03-14
      • 1970-01-01
      相关资源
      最近更新 更多