2017-10-08 77 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的次數,但僅限於視頻播放時。

我相信我必須有一些控制變量,如「isVideoPlaying」,當「視頻播放」事件出現時設置爲true,並且在「視頻暫停」的情況下設置爲false,然後只有在設置爲true時,纔會將「Click Feature 1」事件添加到計數中。

有沒有辦法做到這樣的事情?

+1

更好地流,做在應用端 – sidgate

+0

我認爲這是棘手的做,在我的情況,我有一個B計劃,但我真的很好奇,想知道如果這樣的事情是可能的 –

回答

1

有沒有辦法在 聚合過程中獲取和設置控制變量?

不,在執行聚合管道時無法跟蹤上一個/下一個。

這個想法是將每個事件的事件轉換爲它自己的時間數組值。

您有兩種選擇。

擊穿

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

您可以使用下面聚集

下聚合使用兩個$group階段的事件轉換成其時間序列,然後$project階段項目($let)每個事件創作數組變成一個變量。

對於內部$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 
    ] 
    } 
]) 

您可以通過添加額外的字段「計數」來限制管理陣列生長的任何事件,你可以在一個文檔中存儲。

對於選定的時間片,您可以有多個文檔。

這將簡化到下面的聚合。

以下聚合迭代超過video_play_events並過濾每個播放和暫停對的所有點擊功能(plpu)。

$size計算每個播放和暫停對之間的特徵元素的數目,然後是$map + $sum以計算所有播放暫停對的所有特徵事件。

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 MB的文件限制的風險。

您可以使用異步模塊運行具有適當過濾器的並行查詢,以包含要聚合的數據,然後由客戶端邏輯對所有部分進行計數。

+0

非常感謝您!所以不幸的是,我試圖測試這個,但後來我意識到我與mongodb 5.2卡住和$ indexOfArray是不會工作。所以現在我想我可能不得不重新設計從客戶端發送的內容,或者我必須使用mapReduce。 –

相關問題