簡體   English   中英

帶有Python的Apache Beam中的會話窗口

[英]Session windows in Apache Beam with python

我有一系列的用戶事件。 我已經將它們映射到KV {userId,event},並分配了時間戳。

這將以流模式運行。 我希望能夠創建以下輸入輸出結果:

會話窗口間隔= 1

  • 輸入: user=1, timestamp=1, event=a
  • 輸入: user=2, timestamp=2, event=a
  • 輸入: user=2, timestamp=3, event=a
  • 輸入: user=1, timestamp=2, event=b
  • 時間: lwm=3
  • 輸出: user=1, [ { event=a, timestamp=1 }, { event=b, timestamp=2 } ]
  • 時間: lwm=4
  • 輸出: user=2, [ { event=a, timestamp=2 }, { event=a, timestamp=3 } ]

這樣我就可以編寫函數以減少用戶在會話窗口中的事件列表以及會話窗口的開始和結束時間。

我該怎么寫? (如果回答,請“查看示例”,這不是有效的答案,因為它們從不將事件列表以窗口作為參數輸入到reducer中)

如果我正確理解這一點,那么這將是該問題的后續措施,並且可以通過在我的解決方案中建議的添加按組分組步驟自然完成。

因此,如果我們有這樣的管道,請參考我之前的解釋,並僅關注更改:

events = (p
  | 'Create Events' >> beam.Create(user1_data + user2_data) \
  | 'Add Timestamps' >> beam.Map(lambda x: beam.window.TimestampedValue(x, x['timestamp'])) \
  | 'keyed_on_user_id'      >> beam.Map(lambda x: (x['user_id'], x))
  | 'user_session_window'   >> beam.WindowInto(window.Sessions(session_gap),
                                             timestamp_combiner=window.TimestampCombiner.OUTPUT_AT_EOW) \
  | 'Group' >> beam.GroupByKey() \
  | 'analyze_session'         >> beam.ParDo(AnalyzeSession()))

現在,元素按照問題描述中的描述進行排列,因此我們只需將它們記錄在AnalyzeSession

class AnalyzeSession(beam.DoFn):
  """Prints per session information"""
  def process(self, element, window=beam.DoFn.WindowParam):
    logging.info(element)
    yield element

獲得所需的結果:

INFO:root:('Groot', [{'timestamp': 1554203778.904401, 'user_id': 'Groot', 'value': 'event_0'}, {'timestamp': 1554203780.904401, 'user_id': 'Groot', 'value': 'event_1'}])
INFO:root:('Groot', [{'timestamp': 1554203786.904402, 'user_id': 'Groot', 'value': 'event_2'}])
INFO:root:('Thanos', [{'timestamp': 1554203792.904399, 'user_id': 'Thanos', 'value': 'event_4'}])
INFO:root:('Thanos', [{'timestamp': 1554203784.904398, 'user_id': 'Thanos', 'value': 'event_3'}, {'timestamp': 1554203777.904395, 'user_id': 'Thanos', 'value': 'event_0'}, {'timestamp': 1554203778.904397, 'user_id': 'Thanos', 'value': 'event_1'}, {'timestamp': 1554203780.904398, 'user_id': 'Thanos', 'value': 'event_2'}])

如果要避免使用諸如user_idtimestamp作為值一部分的冗余信息,則可以在“ Map步驟中將其刪除。 根據完整的用例(即減少每個會話級別的聚合事件),我們可以執行類似以下操作的事情:計算事件數或會話持續時間:

class AnalyzeSession(beam.DoFn):
  """Prints per session information"""
  def process(self, element, window=beam.DoFn.WindowParam):
    user = element[0]
    num_events = str(len(element[1]))
    window_end = window.end.to_utc_datetime()
    window_start = window.start.to_utc_datetime()
    session_duration = window_end - window_start

    logging.info(">>> User %s had %s event(s) in %s session", user, num_events, session_duration)

    yield element

以我的示例為例,它將輸出以下內容:

INFO:root:>>> User Groot had 2 event(s) in 0:00:07 session
INFO:root:>>> User Groot had 1 event(s) in 0:00:05 session
INFO:root:>>> User Thanos had 4 event(s) in 0:00:12 session
INFO:root:>>> User Thanos had 1 event(s) in 0:00:05 session

完整代碼在這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM