如何编写一个选择查询或服务器端函数来从许多数据点生成一个整洁的时间流图?

2024-04-06

注意:我正在使用图形数据库(具体来说是 OrientDB)。这让我可以自由地用 javascript 或 groovy 编写服务器端函数,而不是仅限于使用 SQL 来解决这个问题。*

注 2:由于这是一个图形数据库,因此下面的箭头只是描述数据流。我实际上并不需要在查询中返回箭头。箭头代表关系。*

我有以时间流方式表示的数据;即,EventC 在 EventB 之后发生,EventB 在 EventA 之后发生,等等。该数据来自多个源,因此它不是完全线性的。它需要聚集在一起,这就是我遇到的问题。

目前数据看起来像这样:

#     |  event   |  next
--------------------------
12:0  |  EventA  |  12:1
12:1  |  EventB  |  12:2
12:2  |  EventC  |  
12:3  |  EventA  |  12:4
12:4  |  EventD  |  

其中“下一个”是时间流中下一个事件的 out() 边缘。在图表上,结果看起来像:

EventA-->EventB-->EventC
EventA-->EventD

由于这些数据需要聚合在一起,我需要合并重复的事件但保留它们的边缘。换句话说,我需要一个选择查询,该查询将导致:

        -->EventB-->EventC
EventA--|
        -->EventD

在此示例中,由于 Event 和 Event 均在 Event 之后发生(只是在不同时间),因此选择查询将显示 EventA 的两个分支,而不是两个单独的时间流。


EDIT #2

如果要将一组附加数据添加到上面的数据中,使用 EventB->EventE,生成的数据/图表将如下所示:

#     |  event   |  next
--------------------------
12:0  |  EventA  |  12:1
12:1  |  EventB  |  12:2
12:2  |  EventC  |  
12:3  |  EventA  |  12:4
12:4  |  EventD  |  
12:5  |  EventB  |  12:6
12:6  |  EventE  |  

EventA-->EventB-->EventC
EventA-->EventD
EventB-->EventE

我需要一个查询来生成一棵树,例如:

                    -->EventC
        -->EventB--|
        |           -->EventE
EventA--|
        -->EventD

编辑 #3 和 #4

这里显示的数据带有边缘,与上面的“下一”列相反。我还在此处添加了几个附加列,希望能够消除有关数据的任何混淆:

#     |  event   |    ip_address    |       timestamp     |   in   |  out  |
----------------------------------------------------------------------------
12:0  |  EventA  |  123.156.189.18  | 2015-04-17 12:48:01 |        |  13:0 |
12:1  |  EventB  |  123.156.189.18  | 2015-04-17 12:48:32 |  13:0  |  13:1 |
12:2  |  EventC  |  123.156.189.18  | 2015-04-17 12:48:49 |  13:1  |       |
12:3  |  EventA  |  103.145.187.22  | 2015-04-17 14:03:08 |        |  13:2 |
12:4  |  EventD  |  103.145.187.22  | 2015-04-17 14:05:23 |  13:2  |       |
12:5  |  EventB  |  96.109.199.184  | 2015-04-17 21:53:00 |        |  13:3 |
12:6  |  EventE  |  96.109.199.184  | 2015-04-17 21:53:07 |  13:3  |       |

像这样保存数据以保留每个单独的事件和会话流(由 IP 地址标记)。

TL;DR

有很多事件,其中一些是重复的,需要将它们全部组织成一个整洁的时间流程图。


天啊。

经过一个多星期的努力,我想我终于有了一个工作功能。这并未针对性能进行优化(噢,循环!),但在我可以提高性能的同时暂时完成了工作。生成的 OrientDB 服务器端函数(用 javascript 编写):

功能:

// Clear previous runs
db.command("truncate class tmp_Then");
db.command("truncate class tmp_Events");

// Get all distinct events
var distinctEvents = db.query("select from Events group by event");

// Send 404 if null, otherwise proceed
if (distinctEvents == null) {
  response.send(404, "Events not found", "text/plain", "Error: events not found" );
} else {
  var edges = [];

  // Loop through all distinct events
  distinctEvents.forEach(function(distinctEvent) {
    var newEvent = [];
    var rid = distinctEvent.field("@rid");
    var eventType = distinctEvent.field("event");

    // The main query that finds all *direct* descendents of the distinct event
    var result = db.query("select from (traverse * from (select from Events where event = ?) where $depth <= 2) where @class = 'Events' and $depth > 1 and @rid in (select from Events group by event)", [eventType]);

    // Save the distinct event in a temp table to create temp edges
    db.command("create vertex tmp_Events set rid = ?, event = ?", [rid, event]);
      edges.push(result);
    });

  // The edges array defines which edges should exist for a given event
  edges.forEach(function(edge, index) {
    edge.forEach(function(e) {
      // Create the temp edge that corresponds to its distinct event
      db.command("create edge tmp_Then from (select from tmp_Events where rid = " + distinctEvents[index].field("@rid") + ") to (select from tmp_Events where rid = " + e.field("@rid") + ")");
    });
  });

  var result = db.query("select from tmp_Events");
  return result;
}

要点:

  • 临时表似乎是必要的。我尝试在没有临时表(类)的情况下执行此操作,但我不确定是否可以完成。我需要模拟原始数据中不存在的边缘。
  • Traverse 对于编写主查询非常有帮助。遍历一个事件来找到它的直接、独特的后代是相当简单的。
  • 能够用 Javascript 编写存储过程真是太棒了。这对于 SQL 来说将是一场噩梦。
  • omfg 循环。我计划对此进行优化并继续使其变得更好,希望其他人能够找到它的用处。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何编写一个选择查询或服务器端函数来从许多数据点生成一个整洁的时间流图? 的相关文章

随机推荐