0

我在 MongoDB 中有一个带有示例文档的集合,如下所示 -

{
    "_id" : ObjectId("58114e5e43d6420b7db4e15c"),
    "browser" : "Chrome",
    "name": "hyades",
    "country" : "in",
    "day" : "16-10-21",
    "ip" : "0.0.0.0",
    "class" : "A123"
}

问题陈述

我应该能够在获取不同数量的 IP 时对任何字段进行分组。

聚合查询 -

[
    {$group: {_id: '$class', ip_arr: {$addToSet: '$ip'}}},
    {$project: {class: '$_id.class', ip: {$size: '$ip_arr'}}}
]

给出了预期的结果,但速度很慢。ip同样,使用另一个计数$group很慢。输出是 -

[{class: "A123",ip: 42},{class: "B123", ip: 56}..] 

我试过的

我考虑过为此使用 Hyperloglog。我尝试使用 Redis 实现。我尝试流式传输整个数据,仅将我分组的内容投影PFADD到redis中相应的hyperloglog结构中。

逻辑看起来像 -

var stream = Model.find({}, {ip: 1, class: 1}).stream();
stream.on('data', function (doc) {
    var hash = "HLL/" + doc.class;
    client.pfadd(hash, doc.ip);
});

我试图运行这个超过一百万个数据点。要流式传输的数据大小约为 1GB,Mongo 和 Node 服务器之间的连接速度为 1 Gbps。我曾预计这段代码会运行得足够快。但是,它非常慢(比在 MongoDB 中计数要慢)。

我想过但没有实现的另一件事是为每个类预先创建存储桶,并随着数据的流入实时增加它们。但是支持任意分组所需的内存是巨大的,所以不得不放弃这个想法。

请提出我可能做错了什么,或者我可以在这里改进什么,以便我能够充分利用 hyperloglog(我不受 Redis 的限制,并且可以接受任何实现)

4

1 回答 1

0

免责声明:我只使用过来自 C++ 和 Python 的 redis,所以这可能无济于事,但是......

PFADD支持多个参数;在我使用 redis HLL 来计算唯一条目的系统中,我发现将它们批处理并一次发送一个带有许多(大约 100 个)项目的 PFADD 会导致显着的加速 - 大概是由于避免了 redis 客户端往返。

于 2016-11-21T13:59:26.500 回答