mongodb聚合多个未知的嵌套密钥

时间:2013-12-12 10:05:08

标签: mongodb mongodb-query aggregation-framework

我有一个名为'InventoryPerDay'的文档,其中包含每天商店的库存:

{
  _id: "20131202/store_a",
  _metadata: {
    date: ISODate("2013-12-02T00:00:00Z"),
    store: "store_a"
  },
  inventory: {
    quantity: {
      item_44: 1350,
      item_32: 1,
      item_2: 1,
      item_9: 1
    }
  }
},
{
  _id: "20131201/store_a",
  _metadata: {
    date: ISODate("2013-12-01T00:00:00Z"),
    store: "store_a"
  },
  inventory: {
    quantity: {
      item_44: 1000,
      item_32: 5,
      item_2: 10
    }
  }
}

我需要两天内store_a中每件商品的总数量。 “数量”哈希中的项目未知。您可以看到“item_9”存在于2013年12月12日,但不适用于2013年12月1日。

如何使用mongodb中的聚合在多个文档中对未知的嵌套键进行求和?

上述示例的结果应为:

{
  store: "store_a",
  inventory: {
    quantity: {
      item_44: 2350,
      item_32: 6,
      item_2: 11,
      item_9: 1
    }
  }
}

1 个答案:

答案 0 :(得分:8)

不幸的是,你想要做的是Mongodb的当前功能(至少没有聚合)是不可能的,如果你保留你当前的架构,你将不得不使用map-reduce来做这个会慢得多

您可以参考here获取解释,说明您的架构不是最优的原因。

您可以参考here了解如何制作架构以及聚合的外观。

如果您可以将字段的名称投影到值,那么您可以使用当前架构进行查询,这样您可以投票选择this ticket,以便获得更多关注。


更新

您需要更改架构

{
  _id: "20131202/store_a",
  _metadata: {
    date: ISODate("2013-12-02T00:00:00Z"),
    store: "store_a"
  },
  inventory: {
    quantities: [
      { k : "item_44", v: 1350},
      { k : "item_32", v: 1},
      { k : "item_2", v: 1},
      { k : "item_9", v: 1},
    ]
  }
},
.
.
.

,查询应如下所示

db.InventoryPerDay.aggregate(
 [
    {
        "$unwind" : "$inventory.quantities"
    },
    {
        "$group" : {
            "_id" : { "store": "$_metadata.store", "item" : "$inventory.quantities.k"},
            "total" : {
                "$sum" : "$inventory.quantities.v"
            }
        }
    }
])

这会给你一个像这样的结果

{
  result :
   [
    { "_id" : { store : "store_a", item : "item_44"}
      "total" : 2350
    },
    { "_id" : { store : "store_a", item : "item_32"}
      "total" : 6
    },
    { "_id" : { store : "store_a", item : "item_2"}
      "total" : 11
    },
    { "_id" : { store : "store_a", item : "item_9"}
      "total" : 1
    }
  ]
}

您可以使用汇总管道末尾的$ project运算符格式化这些结果。

关于map-reduce与聚合:Map reduce比聚合慢得多,主要原因是它在一个线程上执行。您可以为this ticket投票,以便他们为多个核心实施它,在大多数情况下,使用map-reduce与聚合计算需要花费数量级的时间。