1

次のことを想像してください。

{
    "user" : "john",
    "type" : "connect",
    "created" : ISODate("2015-10-02T10:00:00.000Z"),
    "__v" : 0
},
{
    "user" : "john",
    "type" : "disconnect",
    "created" : ISODate("2015-10-02T10:10:00.000Z"),
    "__v" : 0
},
{
    "user" : "frank",
    "type" : "connect",
    "created" : ISODate("2015-10-02T10:05:00.000Z"),
    "__v" : 0
},
{
    "user" : "frank",
    "type" : "disconnect",
    "created" : ISODate("2015-10-02T10:15:00.000Z"),
    "__v" : 0
},
{
    "user" : "john",
    "type" : "connect",
    "created" : ISODate("2015-10-02T10:15:00.000Z"),
    "__v" : 0
}

「ユーザー john には 5 分間のダウンタイムがありました」という停止レポートを作成したいと考えています。私は今、完全に暗闇の中にいます。集約とmapReduceを掘り下げましたが、必要な方向を指しているようには見えません。プレーンなjavascriptを使用して解決できましたが、MongoDBはそのような種類の集約用に作られているため、それを避けたいと思っています. たぶん、私は頭の中で立ち往生していて、しばらく休ませる必要があるかもしれませんが、誰かが私にとって良い解決策を持っているかもしれません.

したがって、最良の出力は次のようになります(推測します):

{
    "user" : "john",
    "outage": "5"
}

この「最適な」例に加えて、新しいサーバー バージョンを展開するときに、切断がシステムによって飲み込まれる場合があります。それらは約10秒ですが、簡単にするためにそれらを除外することを考えています.

4

1 に答える 1

1

クエリ

db.collection.aggregate([{$group:{_id:{user:"$user",type:"$type"},created:{$max:"$created"}}},{$sort:{"_id.user":1,"_id.type":-1}},{$group:{_id:"$_id.user","latest_disconnected":{"$first":"$created"},"latest_connected":{$last:"$created"}}},{$project:{outage:{$divide:[{"$subtract": [ "$latest_connected", "$latest_disconnected" ] },60000]}}}])

出力

{ "_id": "ジョン", "停止": 5 }

{ "_id" : "フランク"、"停止" : -10 }

詳細説明はこちら

これにより、接続済みおよび切断済みのタイプの各ユーザーの最新のエントリが得られます

{$group:{_id:{user:"$user",type:"$type"},created:{$max:"$created"}}}

ユーザーとタイプでソートすることを忘れないでください。グループはソートされた出力を保証しません

{$sort:{"_id.user":1,"_id.type":-1}}

各ユーザーは前のパイプラインからの 2 つのエントリを持つため、最初のエントリは最新の切断用であり、最後 (2 番目) のエントリは最新の接続用です。

{$group:{_id:"$_id.user","latest_disconnected":{"$first":"$created"},"latest_connected":{$last:"$created"}}}

これは単純な数学であり、2 つの日付の差を分に変換したものです。

{$project:{outage:{$divide:[{"$subtract": [ "$latest_connected", "$latest_disconnected" ] },60000]}}}

それが役立つことを願っています

于 2015-10-02T20:44:43.533 に答える