Dev*_*ung 7 sql graph-databases orientdb
注意:我使用的是图形数据库(OrientDB是特定的).这使我可以自由地在javascript或groovy中编写服务器端函数,而不是将自己限制为SQL以解决此问题.*
注2:由于这是一个图形数据库,下面的箭头只是描述数据流.我不需要在查询中返回箭头.箭头代表关系.*
我有以时间流方式表示的数据; 即EventC发生在EventA之后的EventB之后,等等.这些数据来自多个来源,所以它不是完全线性的.它需要聚集在一起,这就是我遇到问题的地方.
目前数据看起来像这样:
# | event | next
--------------------------
12:0 | EventA | 12:1
12:1 | EventB | 12:2
12:2 | EventC |
12:3 | EventA | 12:4
12:4 | EventD |
Run Code Online (Sandbox Code Playgroud)
其中"next"是时间流中下一个事件的out()边缘.在图表上,这看起来像:
EventA-->EventB-->EventC
EventA-->EventD
Run Code Online (Sandbox Code Playgroud)
由于这些数据需要聚集在一起,我需要合并重复事件但保留它们的边缘.换句话说,我需要一个选择查询,结果将导致:
-->EventB-->EventC
EventA--|
-->EventD
Run Code Online (Sandbox Code Playgroud)
在此示例中,由于EventB和EventD都发生在EventA之后(仅在不同时间),因此select查询将显示EventA的两个分支,而不是两个单独的时间流.
编辑#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
Run Code Online (Sandbox Code Playgroud)
我需要一个查询来生成一个树,如:
-->EventC
-->EventB--|
| -->EventE
EventA--|
-->EventD
Run Code Online (Sandbox Code Playgroud)
编辑#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 | |
Run Code Online (Sandbox Code Playgroud)
数据保存为这样,以保留每个单独的事件和会话流(由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;
}
Run Code Online (Sandbox Code Playgroud)