按照Mongo中Key的值进行分组?

时间:2014-05-22 07:30:49

标签: node.js mongodb mapreduce aggregation-framework

假设我有一些看起来像这样的数据。

[
  { "foo": 1, "bar": "a" },
  { "foo": 2, "bar": "b" },
  { "foo": 3, "bar": "b" },
  { "foo": 4, "bar": "a" }
]

我希望按bar对行进行分组,并将匹配结果存储在对象/地图中的bar值下,如数据结构,就像这样。

{
  "a": [{ "foo": 1, "bar": "a" }, { "foo": 4, "bar": "a" }],
  "b": [{ "foo": 2, "bar": "b" }, { "foo": 3, "bar": "b" }]
}

Mongo有哪些功能来处理这种转换(或类似的东西)?

我当前的方法

我正在使用node.js编写一个Web应用程序,并且我已经设法在javascript(我知道......)中进行了这种转换,但是每当用户查询过于开放且几乎没有约束时,就会产生结果在内存过度分配中,因为我处理大约超过250,000行。当查询返回少于10000行时,我的分组方法有效。

在此之后,我意识到我应该让Mongo为我处理这个问题,特别是因为它导致服务器挂起直到分组完成。我只是不确定如何进行这样的转变。

预选者方法

在我尝试通过网络套接字传输数据后,客户端上的网络工作人员执行此操作之前通过网络工作者分割工作,但它使界面非常明显,&它可能不会在压力下站起来。但至少这不会阻止服务器,也不会导致服务器崩溃。

更多信息

假设是否有bar的所有可能值的列表(我已存储在集合中),我应该进行多次查询吗? &安培;从结果中形成数据结构?

2 个答案:

答案 0 :(得分:2)

aggregation framework相当简单,也是最快的选择,因为聚合框架是本机代码实现,其中像mapReduce这样的东西需要在进程中调用JavaScript解释器:

db.collection.aggregate([
    { "$group": {
        "_id": "$bar",
        "values": { "$push": { "foo": "$foo", "bar": "$bar" } }
    }
])

这需要您对文档结构有所了解。如果您需要更灵活的不同文档,那么您可以使用mapReduce:

db.collection.mapReduce(
    function() {
        emit( this.bar, this );
    },
    function(key, values) {
       return { values: values };
    },
    { "out": { "inline": 1 }
)

不如你的结果那么漂亮,但它完成了工作。

这里唯一真正的问题是你在这里生成的阵列是否真的会炸掉16MB的BSON限制。所以你可能需要对它进行一些细分,但它仍然比获取所有行并在客户端构建更好。

答案 1 :(得分:1)

您可以使用MongoDB Aggregation Framework