我正在使用Neo4j 3.1版,运行我认为非常简单的导入,但遇到了非常严重的问题。我导入有关酒吧的数据(对于非英国用户,公共场所 - 您有品脱和放松的地方!)。 (pl:PubListing)
对(u:BiteUser)
进行了评论,创建了(bc:BiteComment)
。我有两个CSV文件,并且已经导入了(pl:PubListing)
个节点,因此我尝试导入链接到每个发布的评论(pl.source_pub_id
)和每个用户({{1} }})。重要的是,我想将它们作为一种简单的关系加入,并且为了得到一个更好的词语 - 我称之为链条。
通过这种方式,用户发布的最后两条评论(u.username
是最新评论,而bc1
是最新评论但是一条评论)与用户相关联:
第一条评论:
bc2
和第二个:
(u:BiteUser)-[:USER_PREVIOUS_COMMENT]->(bc1), (u)-[:USER_MADE_COMMENT]->(bc1)
到目前为止,非常正常(网络应用中的面包和黄油,注释可能类似于登录事件,密码更改,帖子等)。但是,这并不是在一个简洁的事务中发生,而是在通过CSV加载时。我的查询如下。
N.B。 - 预处理脚本对数据进行排序,以便所有注释按时间顺序排列:最早的注释首先出现,因此没有逻辑将注释放在链中的正确位置。
N.B。 II - 我在这里的几个地方使用(u)-[:USER_MADE_COMMENT]->(bc2), (bc1)-[:USER_PREVIOUS_COMMENT]->(bc2)
而不是创建,因为期望在新数据可用时或在此项目后续跟踪时,查询可能会多次运行(它是' sa谈话)尝试在技术困难后重新导入数据。它不是任何想象力的生产脚本,这里的查询优化不是我的优先事项列表中的首要任务。
MERGE
问题在于,目前它为每个评论创建了两种关系。但是,我在更改查询的开头并在LOAD CSV WITH HEADERS FROM 'file:///output-comments-0031.csv' AS line
// find the pub it refers to
MATCH (pl:PubListing) WHERE pl.source_pub_id = toInteger(line.source_pub_id)
MERGE (u:BiteUser {username: line.username })
// ensure the comment node is created
MERGE (bc:BiteComment { source_comment_id: toInteger(line.source_comment_id) })
SET
// be flexible on scraped input
bc += line,
// indices should be integers, though
bc.source_pub_id = toInteger(line.source_pub_id),
bc.source_comment_id = toInteger(line.source_comment_id),
bc.created_timestamp = toInteger(line.created_timestamp)
// link the comment to the user and pub directly
MERGE (u)-[:USER_MADE_COMMENT]->(bc)
MERGE (bc)-[:COMMENT_ABOUT_PUT]->(pl)
// and in a chain
// - this section will be repeated to link the comment to the
// pub, in a chain. I've only included the user example
// to isolate the problem for SO
WITH u, pl, bc
OPTIONAL MATCH (u)-[r:USER_PREVIOUS_COMMENT]->(lc:BiteComment)
WHERE lc <> bc
WITH u, bc, pl, r, CASE WHEN r IS NULL THEN [] ELSE [1] END AS upc, lc
FOREACH (i IN upc |
DELETE r
CREATE (bc)-[:USER_PREVIOUS_COMMENT]->(lc)
)
// pre-processing means we know this is the most recent comment
// that the graph has seen yet
MERGE (u)-[:USER_PREVIOUS_COMMENT]->(bc)
行之后添加以下行时,因此每个事务加载一个注释,它按预期工作。
LOAD CSV
然后,
WITH line SKIP 0 LIMIT 1
然后......
WITH line SKIP 1 LIMIT 1
......你明白了。
我的问题是这个。 为什么在CSV导入期间会发生这种情况,如何在不将导入作为单个事务运行的情况下停止?
答案 0 :(得分:2)
记住Cypher查询不会每行迭代处理是很重要的。相反,它们同时处理所有行,迭代是对所有行进行的每次操作。
所以你先对所有行进行MATCH,然后对所有行进行MERGE(LOAD CSV之后的第二次操作)等。
您的CSV导入似乎偏离了(错误的)假设迭代处理行,因此您对先前处理的行有某种依赖性,这将无效。
我建议您修复CSV以删除对上一行处理的依赖性。
要么你需要做一个评论的COLLECT(),然后取最后两个条目(比如WITH collectedComments[-2..] as lastTwo
,然后别名每个节点并创建相关的关系),或者你&#39;我需要添加时间戳或其他一些排序方法,然后执行导入后查询以获取最新的两条评论并对其进行排序。