我有一个将文本转换为网络的应用程序,因此当添加一个句子时,每个单词都是一个节点,每个单词的共同出现就是它们之间的连接。此信息对于更好地理解以下问题非常重要。
为了将每个句子添加到Neo4J数据库中,我在Neo4J中有以下Cypher查询,根据我的数据结构,它首先匹配添加节点的user
,然后匹配制作语句的context
(或列表),将其链接到用户,将语句链接到用户和上下文,然后在添加的每个节点(带属性),语句之间创建连接,其中他们被制作了以及制作它们的背景(列表)。
问题是此查询比句子本身长约100,因此如果文本是400Bytes,则查询大约为40K。当我想添加一个长文本时,Neo4J开始变得很慢。
因此 - 我的问题:如何以最佳方式优化此查询?你建议做一组交易吗?
例如,我可以将每个长查询分成多个部分,然后同时发送一些事务以节省时间吗?
我正在谈论一个大约100K长,可能更长的文本。这意味着总请求大约为10Mb。MATCH (u:User {uid: "6e228580-1cb3-11e8-8271-891867c15336"})
MERGE (c_list:Context {name:"list",by:"6e228580-1cb3-11e8-8271-891867c15336",
uid:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47"})
ON CREATE SET c_list.timestamp="15199833288930000"
MERGE (c_list)-[:BY{timestamp:"15199833288930000"}]->(u)
CREATE (s:Statement {name:"#apple #orange #fruit",
text:"apples and oranges are fruits",
uid:"0b56a800-1dfd-11e8-802e-b5cbdf950c47", timestamp:"15199833288930000"})
CREATE (s)-[:BY {context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",
timestamp:"15199833288930000"}]->(u)
CREATE (s)-[:IN {user:"6e228580-1cb3-11e8-8271-891867c15336",
timestamp:"15199833288930000"}]->(c_list)
MERGE (cc_apple:Concept {name:"apple"})
ON CREATE SET cc_apple.timestamp="15199833288930000", cc_apple.uid="0b56a801-1dfd-11e8-802e-b5cbdf950c47"
MERGE (cc_orange:Concept {name:"orange"})
ON CREATE SET cc_orange.timestamp="15199833288930000", cc_orange.uid="0b56cf10-1dfd-11e8-802e-b5cbdf950c47"
MERGE (cc_fruit:Concept {name:"fruit"})
ON CREATE SET cc_fruit.timestamp="15199833288930002", cc_fruit.uid="0b56cf13-1dfd-11e8-802e-b5cbdf950c47"
CREATE (cc_apple)-[:BY {context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",timestamp:"15199833288930000",
statement:"0b56a800-1dfd-11e8-802e-b5cbdf950c47"}]->(u)
CREATE (cc_apple)-[:OF {context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",user:"6e228580-1cb3-11e8-8271-891867c15336",timestamp:"15199833288930000"}]->(s)
CREATE (cc_apple)-[:AT {user:"6e228580-1cb3-11e8-8271-891867c15336",timestamp:"15199833288930000",
context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",statement:"0b56a800-1dfd-11e8-802e-b5cbdf950c47"}]->(c_list)
CREATE (cc_apple)-[:TO {context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",
statement:"0b56a800-1dfd-11e8-802e-b5cbdf950c47",user:"6e228580-1cb3-11e8-8271-891867c15336",
timestamp:"15199833288930000",uid:"0b56cf11-1dfd-11e8-802e-b5cbdf950c47",gapscan:"2",weight:"3"}]->(cc_orange)
CREATE (cc_orange)-[:BY {context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",timestamp:"15199833288930000",statement:"0b56a800-1dfd-11e8-802e-b5cbdf950c47"}]->(u)
CREATE (cc_orange)-[:OF {context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",user:"6e228580-1cb3-11e8-8271-891867c15336",timestamp:"15199833288930000"}]->(s)
CREATE (cc_orange)-[:AT {user:"6e228580-1cb3-11e8-8271-891867c15336",timestamp:"15199833288930000",
context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",statement:"0b56a800-1dfd-11e8-802e-b5cbdf950c47"}]->(c_list)
CREATE (cc_orange)-[:TO {context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",
statement:"0b56a800-1dfd-11e8-802e-b5cbdf950c47",user:"6e228580-1cb3-11e8-8271-891867c15336",
timestamp:"15199833288930002",uid:"0b56cf14-1dfd-11e8-802e-b5cbdf950c47",gapscan:"2",weight:"3"}]->(cc_fruit)
CREATE (cc_apple)-[:TO {context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",
statement:"0b56a800-1dfd-11e8-802e-b5cbdf950c47",user:"6e228580-1cb3-11e8-8271-891867c15336",
timestamp:"15199833288930002",uid:"0b56cf16-1dfd-11e8-802e-b5cbdf950c47",gapscan:"4",weight:"2"}]->(cc_fruit)
CREATE (cc_fruit)-[:BY {context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",
timestamp:"15199833288930002",statement:"0b56a800-1dfd-11e8-802e-b5cbdf950c47"}]->(u)
CREATE (cc_fruit)-[:OF {context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",user:"6e228580-1cb3-11e8-8271-891867c15336",timestamp:"15199833288930002"}]->(s)
CREATE (cc_fruit)-[:AT {user:"6e228580-1cb3-11e8-8271-891867c15336",
timestamp:"15199833288930002",context:"0b4fa320-1dfd-11e8-802e-b5cbdf950c47",
statement:"0b56a800-1dfd-11e8-802e-b5cbdf950c47"}]->(c_list)
RETURN s.uid;
答案 0 :(得分:1)
1)使用输入parameters
:
var params = {
userId: "6e228580-1cb3-11e8-8271-891867c15336",
contextName: "list",
time: "15199833288930000",
statementName: "#apple #orange #fruit",
statementText: "apples and oranges are fruits",
concepts: ["apple", "orange", "fruit"],
conceptsRelations: [
{from: "apple", to: "orange", gapscan: 2, weight: 3},
{from: "orange", to: "fruit", gapscan: 2, weight: 3},
{from: "apple", to: "fruit", gapscan: 4, weight: 2}
]
}
session.run(cypherQuery, params).then...
2)使用APOC library
在数据库端生成唯一标识符:apoc.create.uuid()
3)使用循环(foreach和unwind)进行重复操作:
MATCH (u:User {uid: $userId})
MERGE (c_list:Context {name: $contextName, by: $userId})
ON CREATE SET c_list.timestamp = $time,
c_list.uid = apoc.create.uuid()
MERGE (c_list)-[:BY{timestamp: $time}]->(u)
CREATE (s:Statement {name: $statementName,
text: $statementText, uid:apoc.create.uuid(), timestamp: $time})
CREATE (s)-[:BY {context: c_list.uid, timestamp: $time}]->(u)
CREATE (s)-[:IN {user: u.uid, timestamp: $time}]->(c_list)
FOREACH (conceptName in $concepts|
MERGE (concept:Concept {name: conceptName})
ON CREATE SET concept.timestamp = $time,
concept.uid = apoc.create.uuid()
CREATE (concept)-[:BY {context: c_list.uid, timestamp: $time, statement: s.uid}]->(u)
CREATE (concept)-[:OF {context: c_list.uid, user: u.uid, timestamp: $time}]->(s)
CREATE (concept)-[:AT {user: u.uid, timestamp: $time,
context: c_list.uid, statement: s.uid}]->(c_list)
)
WITH u, c_list, s
UNWIND $conceptsRelations as conceptsRelation
MATCH (c_from:Concept {name: conceptsRelation.from})
MATCH (c_to:Concept {name: conceptsRelation.to})
CREATE (c_from)-[:TO {context: c_list.uid, statement: s.uid, user: u.uid,
timestamp: $time, uid: apoc.create.uuid(),
gapscan: conceptsRelation.gapscan,
weight: conceptsRelation.weight}]->(c_to)
RETURN distinct s.uid;