0

これは、集計フレームワークでこの問題を解決しようとしたこの質問のフォローアップです。残念ながら、この特定の 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 } }

偶数の索引付けされたドキュメントには、customers と original_stock がリストされていますが、num_sold の合計が正しくありません。奇数の索引付けされたドキュメントには num_sold しかリストされていませんが、これは正しい数です。

何が欠けているのか誰か教えてください。

4

1 に答える 1

1

あなたの問題は、reduce 関数の出力の形式が map 関数の形式と同じでなければならないという事実によるものです (説明については、reduce 関数の要件を参照してください)。

問題を解決するには、コードを次のように変更する必要があります。

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マップ機能の変更。私はそれがあなたが望むものだと思います

于 2013-05-24T21:53:58.040 に答える