在 neo4j 的关系中跟踪日志的最佳方式
Best way of keeping track of logs within a relationship in neo4j
坦率地说,我对使用 Neo4j 还很陌生。
阅读了大量文档后,我想知道 存储具有时间戳等数据类型的访问 "logs" 的最佳方式是什么?
例如,我有以下关系:
[u:用户]-(已访问)->[p:公园]
我应该为 Visited 创建一个包含多个时间戳的列表属性吗?
或者我应该在包含每个唯一时间戳的两个实体之间建立多个 "Visited" 关系?
在两个实体之间生成多个关系似乎是一种开销。
我觉得我在使用这种类型的数据库时缺少一个关键概念。
非常感谢,
Or should I make multiple "Visited" Relationships between the two entities containing each a unique timestamp?
生成多个关系很好——图形数据库是为这种工作负载量身定制的,因此它们非常擅长有效地处理它。这样,添加和删除新访问非常简单。例如,如果您使用 ID 标识用户和公园,则此类查询将起作用。
添加新访问:
MATCH (u:User {id: $userId}), (p:Park {id: $parkId})
CREATE (u)-[:VISITED {timestamp: $timestamp}]->(p)
删除访问:
MATCH (:User {id: $userId})-[v:VISITED {timestamp: $timestamp}]->(:Park {id: $parkId})
DELETE v
查询用户的所有时间戳也很容易:
MATCH (:User {id: $userId})-[v:VISITED]->(:Park {id: $parkId})
RETURN collect(v.timestamp)
Should I create a list attribute for Visited containing multiple timestamps?
属性列表可以写在纸上,但会使查询变得非常麻烦:
MATCH (u:User {id: $userId})-[v:VISITED]->(p:Park {id: $parkId})
SET v.timestamps = coalesce(v.timestamps, []) + [$timestamp]
(coalesce
方法 returns 第一个非空值——所以如果 timestamps
属性 没有初始化,它 returns 一个开头为空列表。)
当然,这种表示使得查询所有时间戳更加简单:
MATCH (u:User {id: $userId})-[v:VISITED]->(p:Park {id: $parkId})
RETURN coalesce(v.timestamps, [])
然而,检查某个用户时间戳公园访问是否发生变得更加困难并且(大概)慢得多:
MATCH (u:User {id: $userId})-[v:VISITED]->(p:Park {id: $parkId})
WHERE $timestamp IN v.timestamps
RETURN v
此外,删除时间戳不再是小事:
MATCH (u:User {id: $userId})-[v:VISITED]->(p:Park {id: $parkId})
SET v.timestamps = [timestamp IN v.timestamps WHERE timestamp <> $timestamp]
关于时间戳的说明。 vanilla Neo4j 中没有时间戳。常见的解决方法包括使用 epoch time or a string with a specific format, e.g. ISO 8601. If you're use case requires to handle timestamps in a more sophisticated way, consider using the conversion methods offered by the APOC library.
坦率地说,我对使用 Neo4j 还很陌生。 阅读了大量文档后,我想知道 存储具有时间戳等数据类型的访问 "logs" 的最佳方式是什么? 例如,我有以下关系: [u:用户]-(已访问)->[p:公园] 我应该为 Visited 创建一个包含多个时间戳的列表属性吗? 或者我应该在包含每个唯一时间戳的两个实体之间建立多个 "Visited" 关系? 在两个实体之间生成多个关系似乎是一种开销。 我觉得我在使用这种类型的数据库时缺少一个关键概念。 非常感谢,
Or should I make multiple "Visited" Relationships between the two entities containing each a unique timestamp?
生成多个关系很好——图形数据库是为这种工作负载量身定制的,因此它们非常擅长有效地处理它。这样,添加和删除新访问非常简单。例如,如果您使用 ID 标识用户和公园,则此类查询将起作用。
添加新访问:
MATCH (u:User {id: $userId}), (p:Park {id: $parkId})
CREATE (u)-[:VISITED {timestamp: $timestamp}]->(p)
删除访问:
MATCH (:User {id: $userId})-[v:VISITED {timestamp: $timestamp}]->(:Park {id: $parkId})
DELETE v
查询用户的所有时间戳也很容易:
MATCH (:User {id: $userId})-[v:VISITED]->(:Park {id: $parkId})
RETURN collect(v.timestamp)
Should I create a list attribute for Visited containing multiple timestamps?
属性列表可以写在纸上,但会使查询变得非常麻烦:
MATCH (u:User {id: $userId})-[v:VISITED]->(p:Park {id: $parkId})
SET v.timestamps = coalesce(v.timestamps, []) + [$timestamp]
(coalesce
方法 returns 第一个非空值——所以如果 timestamps
属性 没有初始化,它 returns 一个开头为空列表。)
当然,这种表示使得查询所有时间戳更加简单:
MATCH (u:User {id: $userId})-[v:VISITED]->(p:Park {id: $parkId})
RETURN coalesce(v.timestamps, [])
然而,检查某个用户时间戳公园访问是否发生变得更加困难并且(大概)慢得多:
MATCH (u:User {id: $userId})-[v:VISITED]->(p:Park {id: $parkId})
WHERE $timestamp IN v.timestamps
RETURN v
此外,删除时间戳不再是小事:
MATCH (u:User {id: $userId})-[v:VISITED]->(p:Park {id: $parkId})
SET v.timestamps = [timestamp IN v.timestamps WHERE timestamp <> $timestamp]
关于时间戳的说明。 vanilla Neo4j 中没有时间戳。常见的解决方法包括使用 epoch time or a string with a specific format, e.g. ISO 8601. If you're use case requires to handle timestamps in a more sophisticated way, consider using the conversion methods offered by the APOC library.