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);
});

これを100万以上のデータポイントで実行しようとしました。ストリーミングされるデータのサイズは約 1GB で、Mongo と Node サーバー間の接続は 1 Gbps でした。このコードは十分に高速に実行されると予想していました。ただし、かなり遅かったです (MongoDB でのカウントよりも遅かった)。

私が考えたが実装しなかったもう 1 つのことは、各クラスのバケットを事前に作成し、流入するデータに合わせてリアルタイムでバケットをインクリメントすることでした。

私が間違っている可能性があること、またはここで改善できることを提案して、hyperloglog を最大限に活用できるようにします (私は Redis に制約されておらず、あらゆる実装にオープンです)。

4

1 に答える 1

0

Disclaimer: I've only used redis from C++ & Python, so this may not help, but...

PFADD supports multiple arguments; In a system where I was using redis HLL for counting unique entries, I found that batching them and sending a single PFADD with many (of the order of 100) items in one go resulted in a significant speedup - presumably due to avoiding the redis client round-trip.

于 2016-11-21T13:59:26.500 に答える