根据事件顺序创建关系

时间:2016-12-11 14:18:40

标签: neo4j cypher

我有一张CSV,其中包含以下列的事件日志:EventTypeUserIdRecordId(自动递增的序列号)。我想导入到Neo4j并为每个EventType(大约100种唯一类型)构建一个节点,然后使用关系分析路径。要建立关系,我需要匹配所有原始事件并在路径中找到“下一个”事件,这意味着我需要将它与具有相同UserId且下一个RecordId的事件匹配的事件大于当前事件RecordIdnext RecordId > current RecordId)。 在Cypher中执行此操作的有效方法是什么?不知怎的,我提出了涉及笛卡尔积的查询,这些查询非常慢。

1 个答案:

答案 0 :(得分:0)

我认为在这种情况下你无法避免使用笛卡尔积。但是,你可以

  1. 让它们尽可能小。
  2. 使用索引编制来提高查询速度。
  3. 除了使用EventType作为节点标签(“唯一类型”)之外,我强烈建议为所有事件使用额外的Event标签,以便您可以索引userId值和recordId值。

    CREATE INDEX ON :Event(recordId)
    CREATE INDEX ON :Event(userId)
    

    我创建了一个小示例数据集:

    CREATE
      (e1:Event:Skating {userId: 1, recordId: 1}),
      (e2:Event:Hiking {userId: 1, recordId: 2}),
      (e3:Event:Mountaineering {userId: 1, recordId: 3})
    

    要获得下一个recordId,您需要满足nextRecordId > currentRecordId并且nextRecordId必须是最小的(因为recordId来自自动递增序列)。我们使用MERGE连接这两个事件(CREATE也可以,但使用MERGE可以确保我们避免创建重复的边缘。这给出了以下查询:

    MATCH (a:Event), (b:Event)
    WHERE a.userId = b.userId
      AND a.recordId < b.recordId
    WITH a, min(b.recordId) AS bRecordId
    MATCH (b {recordId: bRecordId})
    MERGE (a)-[:NEXT]->(b)
    

    此查询为所有用户ID创建笛卡尔积。只要用户不参与数百个活动,笛卡尔产品的规模就不应该增长。请注意,第一个MATCH使用两个索引(userIdrecordId),而第二个MATCH使用recordId上的索引。