在相同标签的节点之间创建关系?

问题描述 投票:0回答:1

我有一个从 csv 导入的建筑风格时期数据库。每个

Style
都有一个
styId
,还有一个
infId
,显示了影响它的先前风格。

如果提到风格有影响,我想在风格之间建立关系,如下所示:

受罗马风格影响的盎格鲁撒克逊风格

Anglo-saxon style influenced by Roman style

styId 和 infId 具有匹配的值

styId and infId with matching values

我知道这将是将

styId
infId
进行匹配,但我不是数据科学家,而且对 NEO4j 非常陌生。我可以通过手动指定关系来做到这一点,但我正在自己构建此数据集,并计划稍后添加更多条目,因此,如果有最佳实践通过单独使用
styId
infId
来创建这些关系,我更喜欢这个选项。

感谢您的帮助,如果有任何不清楚的地方请告诉我。

neo4j cypher
1个回答
0
投票

如果数据库中已有数据,则可以使用如下查询。创建关系后,它还会删除多余的

infId
属性。

MATCH (s1:Style)
WITH s1, SPLIT(s1.infId, ';') AS infs
MATCH (s2:Style)
WHERE s2.styId IN infs
CREATE (s1)-[:INFLUENCED_BY]->(s2)
REMOVE s1.infId // Remove redundant infId property

首先,你应该在styId

Style
属性上创建一个
index
,以加快查询速度:

CREATE INDEX Style_styId FOR (s:Style) ON (s.styId)

替代建议

但是,更好的是,您应该在将数据提取到数据库时创建所需的数据模型,而不是事后修复数据库。

有多种方法可以将 CSV 导入 Neo4j。最简单的是通过 LOAD CSV,所以这里是一个例子。假设您的 CSV 文件有标题行:

CALL {
  LOAD CSV WITH HEADERS FROM 'file:///styles.csv' AS r
  CREATE (s:Style {id: r.styId, name: r.Style, dates: r.Dates, influences: SPLIT(r.Influences, ';')})
  MERGE (loc:Location {name: r.Location})
  CREATE (s)-[:LOCATION]->(l)
}
LOAD CSV WITH HEADERS FROM 'file:///styles.csv' AS row
MATCH (s1:Style)
WHERE s1.id = row.styId
WITH s1, SPLIT(s1.infId, ';') AS infs
MATCH (s2:Style)
WHERE s2.id IN infs
CREATE (s1)-[:INFLUENCED_BY]->(s2)

如果您有多个位置,您可能还想在

Location.name
上创建索引。

请注意,这会创建一个与您的数据模型略有不同的数据模型,因为:

  • 每个

    Style
    节点都指向唯一的
    Location
    节点

  • influences
    属性(您可能想省略)是一个字符串列表

  • styId
    存储为
    id
    属性(因为很明显 id 是用于样式的)。这要求你的 id 索引是这样创建的:

    CREATE INDEX Style_id FOR (s:Style) ON (s.id)
    

通过 CSV 文件中的 2 次导入完成摄取;第一个用于创建所有

Style
节点,第二个用于创建所有
INFLUENCED_BY
关系。 CALL 子查询 用于干净地分离 2 个
LOAD CSV
调用(否则,您需要在它们之间执行聚合,只是为了将行数减少到 1)。

上述解决方案假设您没有很多样式,因此它在单个事务中完成所有操作。如果您有很多样式,则必须更改(并且可能拆分)查询以避免内存不足和/或花费太长时间。

© www.soinside.com 2019 - 2024. All rights reserved.