我有一个 Node.Js 应用程序的任务,该应用程序将文本转换为网络(单词是 Node ,它们的同时出现 - 具有多个权重 - 是网络图中的连接),我需要在其中保存所有数据存入 Neo4J 数据库。
正如你可以想象的,虽然它适用于简短的语句,但一旦它们变得更长,例如 5000 个单词,其中词汇量约为 500 个唯一单词,我就需要保存大量 Node 和大量连接到数据库。目前,我有一个这样的请求:
MATCH (u:User {uid: "15229100-b20e-11e3-80d3-6150cb20a1b9"})
MERGE (c_0:Context {name:"st",by:u.uid,uid:"d0342000-1c4c-11e9-b9f6-e1addb3b0fa7"})
ON CREATE SET c_0.timestamp="15479451847980000" MERGE (c_0)-[:BY{timestamp:"15479451847980000"}]->(u)
CREATE (s:Statement {name:"#apple #orange #fruit", text:"apples and oranges are fruits", uid:"d0390200-1c4c-11e9-b9f6-e1addb3b0fa7", timestamp:"15479451847980000"})
CREATE (s)-[:BY {context:c_0.uid,timestamp:s.timestamp}]->(u)
CREATE (s)-[:IN {user:u.id,timestamp:s.timestamp}]->(c_0)
MERGE (cc_0:Concept {name:"apple"})
ON CREATE SET cc_0.uid="d0390201-1c4c-11e9-b9f6-e1addb3b0fa7"
MERGE (cc_1:Concept {name:"orange"})
ON CREATE SET cc_1.uid="d0390204-1c4c-11e9-b9f6-e1addb3b0fa7"
MERGE (cc_2:Concept {name:"fruit"})
ON CREATE SET cc_2.uid="d0390207-1c4c-11e9-b9f6-e1addb3b0fa7"
CREATE (cc_0)-[:BY {context:c_0.uid,timestamp:s.timestamp,statement:s.uid}]->(u)
CREATE (cc_0)-[:OF {context:c_0.uid,user:u.uid,timestamp:s.timestamp}]->(s)
CREATE (cc_0)-[:AT {user:u.uid,timestamp:s.timestamp,context:c_0.uid,statement:s.uid}]->(c_0)
CREATE (cc_0)-[:TO {context:c_0.uid,statement:s.uid,user:u.uid,timestamp:"15479451847980000",uid:"d0390205-1c4c-11e9-b9f6-e1addb3b0fa7",gapscan:"2",weight:"3"}]->(cc_1)
CREATE (cc_1)-[:BY {context:c_0.uid,timestamp:"15479451847980000",statement:s.uid}]->(u) CREATE (cc_1)-[:OF {context:c_0.uid,user:u.uid,timestamp:"15479451847980000"}]->(s)
CREATE (cc_1)-[:AT {user:u.uid,timestamp:"15479451847980000",context:c_0.uid,statement:s.uid}]->(c_0)
CREATE (cc_1)-[:TO {context:c_0.uid,statement:s.uid,user:u.uid,timestamp:"15479451847980002",uid:"d0390208-1c4c-11e9-b9f6-e1addb3b0fa7",gapscan:"2",weight:"3"}]->(cc_2)
CREATE (cc_0)-[:TO {context:c_0.uid,statement:s.uid,user:u.uid,timestamp:"15479451847980002",uid:"d039020a-1c4c-11e9-b9f6-e1addb3b0fa7",gapscan:"4",weight:"2"}]->(cc_2)
CREATE (cc_2)-[:BY {context:c_0.uid,timestamp:"15479451847980002",statement:s.uid}]->(u)
CREATE (cc_2)-[:OF {context:c_0.uid,user:u.uid,timestamp:"15479451847980002"}]->(s)
CREATE (cc_2)-[:AT {user:u.uid,timestamp:"15479451847980002",context:c_0.uid,statement:s.uid}]->(c_0)
RETURN s.uid;
对于这一段文字:
apples and oranges are fruits
如您所见,结果比必要的要长得多。
目前,对于较长的文本,我只是将 Cypher 请求分成较小的 block ,然后将它们在事务中提供给数据库。
但是,这仍然相当慢 - 每 KB 文本大约需要一秒。
我的查询是用 Javascript/Node.Js 构建的:https://github.com/noduslabs/infranodus/blob/master/lib/db/neo4j.js#L116
基本逻辑是:
如果有一句话苹果和橙子是水果
我需要为每个 Node 创建一个 Node ,将它们链接到创建它们的
用户
以及语句
本身和graph
(一个图可以有多个语句)。然后我需要在这些具有不同权重的单词之间创建连接:
[苹果 - 橙子]
[橙子 - 水果]
[苹果 - 水果]
...
对于 300 个单词的序列,什么是有效的方法?
我知道我可以使用 FOREACH
循环和 params
以及 apoc
来生成 UID,但这真的会让查询更高效吗与使用 JavaScript 构建相比?我不太明白如何在我的集合上执行此操作,以及它是否有助于解决对于 300 多个单词序列来说太重的问题。
这些做法有帮助吗?我如何将它们实现到此 Cypher 查询中?
最佳答案
我认为问题更多的是庞大的语句,必须对其进行解析、编译和计划。
最好使用批量参数作为输入,并让 cypher 进行迭代, 参见
您需要所有 UUID 做什么?
您是否为 MERGE 操作设置了索引和约束?
关于javascript - 如何对 Neo4J : optimize Cypher or improve the Javascript/Node. Js 构造函数进行高效快速的长查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54272622/