2017-10-08 12 views
1

それが理解しやすいですので、私は私の特定の問題を単純化してきたが、私は集約したいデータがビデオプレーヤーのページで、ユーザーイベントであり、それは次のようになりますので、イベントは一貫してオンになっている集約プロセス中に制御変数を取得して設定する方法はありますか?

{_id:"5963796a46d12ed9891f8c80",eventName:"Click Freature 1",creation:1499691279492}, 
{_id:"59637a5a46d12ed9891f8e0d",eventName:"Video Play",creation:1499691608106}, 
{_id:"59637a9546d12ed9891f8e90",eventName:"Click Freature 1",creation:1499691664633}, 
{_id:"59637c0f46d12ed9891f9146",eventName:"Video Pause",creation:1499692055335} 

年代順ユーザーが機能1をクリックした回数をカウントしたいとしますが、ビデオが再生されているときだけです。

「ビデオ再生」イベントが発生したときにtrueに設定され、「ビデオポーズ」の場合にはfalseに設定されている「isVideoPlaying」のような制御変数を持つ必要があると思いますtureに設定されている場合にのみ、「Click Feature 1」イベントをカウントに追加します。

これを行う方法はありますか?

+1

アプリケーションの側でより良いストリームとする – sidgate

+0

私のケースでは、これを行うのは難しいと思いますが、私はプランBを持っていますが、この種のことが可能かどうかを知りたいのは本当に興味があります –

答えて

1

アグリゲーションプロセス中に制御変数を取得して設定する方法はありますか?

いいえ、アグリゲーションパイプラインが実行されたときの前後を追跡する方法はありません。

考えられるのは、各イベントのイベントを独自のタイムアレイ値に変換することです。

2つのオプションがあります。

内訳

Video Play :    [1,5,7] 
Video Pause :   [3,6,10] 
Features :    [2,4,8,9] 

Play-Features :   2   8,9   
Video play-pause pair : [1,3],[5,6],[7,10] 
Pause-Features :   4    
Video pause-play pair : [3,5],[6,7],[10,-] 

予想される出力

{count:3} 

まずオプション:イベントに文書を変換するために

利用エクストラステージ(あなたがアグリゲーションパイプラインのすべての作業を行います)アレイ構造。

あなたは集計の下に使用できる文書

db.collection.insertMany([ 
{eventName:"Video Play",creation:1}, 
{eventName:"Click Features 1",creation:2}, 
{eventName:"Video Pause",creation:3}, 
{eventName:"Click Features 1",creation:4}, 
{eventName:"Video Play",creation:5}, 
{eventName:"Video Pause",creation:6}, 
{eventName:"Video Play",creation:7}, 
{eventName:"Click Features 1",creation:8}, 
{eventName:"Click Features 1",creation:9}, 
{eventName:"Video Pause",creation:10} 
]); 

の下に考えてみましょう

凝集は、以下のプロジェクトに$project段階($let)各イベントの創造に続いてその時間配列にイベントを変換するために2つの$groupのステージを使用しています配列を変数に変換します。あなたはこの時点では、各イベントのイベント創作配列を持つ* $let内部ロジック説明について

はオプション2

db.collection.aggregate([ 
    { 
    "$sort": { 
     "eventName": 1, 
     "creation": 1 
    } 
    }, 
    { 
    "$group": { 
     "_id": "$eventName", 
     "creations": { 
     "$push": "$creation" 
     } 
    } 
    }, 
    { 
    "$group": { 
     "_id": "null", 
     "events": { 
     "$push": { 
      "eventName": "$_id", 
      "creations": "$creations" 
     } 
     } 
    } 
    }, 
    { 
    "$project": { 
     "count": { 
     "$let": { 
      "vars": { 
      "video_play_events": { 
       "$arrayElemAt": [ 
       "$events.creations", 
       { 
        "$indexOfArray": [ 
        "$events.eventName", 
        "Video Play" 
        ] 
       } 
       ] 
      }, 
      "click_features_event": { 
       "$arrayElemAt": [ 
       "$events.creations", 
       { 
        "$indexOfArray": [ 
        "$events.eventName", 
        "Click Features 1" 
        ] 
       } 
       ] 
      }, 
      "video_pause_events": { 
       "$arrayElemAt": [ 
       "$events.creations", 
       { 
        "$indexOfArray": [ 
        "$events.eventName", 
        "Video Pause" 
        ] 
       } 
       ] 
      } 
      }, 
      "in": {*} 
     } 
     } 
    } 
    } 
]) 

を参照してください。集約コードの下に挿入し、$video_play_events$$video_play_eventsなどに置き換えて、$letステージの変数にアクセスします。

番目のオプション:(あなたは独自の配列内のイベントを保存)

db.collection.insert([ 
    { 
    "video_play_events": [ 
     1, 
     5, 
     7 
    ], 
    "click_features_event": [ 
     2, 
     4, 
     8, 
     9 
    ], 
    "video_pause_events": [ 
     3, 
     6, 
     10 
    ] 
    } 
]) 

あなたは一つの文書に格納できるイベントの一切を制限するために余分なフィールド「count」を追加することにより、配列の成長を管理することはできません。

選択したタイムスライスに複数のドキュメントを含めることができます。

これにより、以下の集約が簡素化されます。

以下の集計は、video_play_eventsを繰り返し、各再生と一時停止のペア(plpu)のすべてのクリック機能をフィルタリングします。全てのプレイポーズペアのすべての機能のイベントをカウントする$map + $sum続く各プレイとポーズ対の間の機能要素のnoをカウントする

$size

db.collection.aggregate([ 
    { 
    "$project": { 
     "count": { 
     "$sum": { 
      "$map": { 
      "input": { 
       "$range": [ 
       0, 
       { 
        "$subtract": [ 
        { 
         "$size": "$video_play_events" 
        }, 
        1 
        ] 
       } 
       ] 
      }, 
      "as": "z", 
      "in": { 
       "$let": { 
       "vars": { 
        "pl": { 
        "$arrayElemAt": [ 
         "$video_pause_events", 
         "$$z" 
        ] 
        }, 
        "pu": { 
        "$arrayElemAt": [ 
         "$video_play_events", 
         { 
         "$add": [ 
          1, 
          "$$z" 
         ] 
         } 
        ] 
        } 
       }, 
       "in": { 
        "$size": { 
        "$filter": { 
         "input": "$click_features_event", 
         "as": "fe", 
         "cond": { 
         "$and": [ 
          { 
          "$gt": [ 
           "$$fe", 
           "$$pl" 
          ] 
          }, 
          { 
          "$lt": [ 
           "$$fe", 
           "$$pu" 
          ] 
          } 
         ] 
         } 
        } 
        } 
       } 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
]) 

注:

あなたはどちらの場合に集約しようとしている文書の一切に基づいていない16メガバイトの文書の上限を打つのリスクを実行します。

非同期モジュールを使用すると、適切なフィルタを使用して並列クエリを実行して、集計するデータを格納し、その後にすべてのパーツを数えるクライアント側のロジックを含めることができます。

+0

ありがとう!だから不運にも私はこれをテストしようとしていましたが、mongodb 5.2と$ indexOfArrayで動かないことに気付きました。ですから、私はおそらくクライアントから送られたものを再設計するか、mapReduceを代わりに使用しなければならないと思います。 –

関連する問題