我有一张CSV,其中包含以下列的事件日志:EventType
,UserId
,RecordId
(自动递增的序列号)。我想导入到Neo4j并为每个EventType
(大约100种唯一类型)构建一个节点,然后使用关系分析路径。要建立关系,我需要匹配所有原始事件并在路径中找到“下一个”事件,这意味着我需要将它与具有相同UserId
且下一个RecordId
的事件匹配的事件大于当前事件RecordId
(next RecordId > current RecordId
)。
在Cypher中执行此操作的有效方法是什么?不知怎的,我提出了涉及笛卡尔积的查询,这些查询非常慢。
答案 0 :(得分:0)
我认为在这种情况下你无法避免使用笛卡尔积。但是,你可以
除了使用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
使用两个索引(userId
和recordId
),而第二个MATCH
使用recordId
上的索引。