在Neo4J Cypher查询中,属性值只能是原始类型或其数组

时间:2019-01-22 19:58:52

标签: neo4j cypher

我设置了以下params

:params "userId":"15229100-b20e-11e3-80d3-6150cb20a1b9",
"contextNames":[{"uid":"94e71bf0-1e7d-11e9-8f33-4f0c99ea0da1","name":"zhora"}],
"statements":[{"text":"oranges apples bananas","concepts":["orange","apple","banana"],
"mentions":[],"timestamp":15481867295710000,"name":"# banana","uid":"34232870-1e7f-11e9-8609-a7f6b478c007",
"uniqueconcepts":[{"name":"orange","suid":"34232870-1e7f-11e9-8609-a7f6b478c007","timestamp":15481867295710000},{"name":"apple","suid":"34232870-1e7f-11e9-8609-a7f6b478c007","timestamp":15481867295710000},{"name":"banana","suid":"34232870-1e7f-11e9-8609-a7f6b478c007","timestamp":15481867295710000}],"uniquementions":[]}],"timestamp":15481867295710000,"conceptsRelations":[{"from":"orange","to":"apple","context":"94e71bf0-1e7d-11e9-8f33-4f0c99ea0da1","statement":"34232870-1e7f-11e9-8609-a7f6b478c007","user":"15229100-b20e-11e3-80d3-6150cb20a1b9","timestamp":15481867295710000,"uid":"apoc.create.uuid()","gapscan":"2","weight":3},{"from":"apple","to":"banana","context":"94e71bf0-1e7d-11e9-8f33-4f0c99ea0da1","statement":"34232870-1e7f-11e9-8609-a7f6b478c007","user":"15229100-b20e-11e3-80d3-6150cb20a1b9","timestamp":15481867295710002,"uid":"apoc.create.uuid()","gapscan":"2","weight":3},{"from":"orange","to":"banana","context":"94e71bf0-1e7d-11e9-8f33-4f0c99ea0da1","statement":"34232870-1e7f-11e9-8609-a7f6b478c007","user":"15229100-b20e-11e3-80d3-6150cb20a1b9","timestamp":15481867295710002,"uid":"apoc.create.uuid()","gapscan":4,"weight":2}],"mentionsRelations":[] 

然后当我进行以下查询时:

MATCH (u:User {uid: $userId}) 
UNWIND $contextNames as contextName 
MERGE (context:Context {name:contextName.name,by:u.uid,uid:contextName.uid}) 
ON CREATE SET context.timestamp=$timestamp 
MERGE (context)-[:BY{timestamp:$timestamp}]->(u) 
WITH u, context 
UNWIND $statements as statement 
CREATE (s:Statement {name:statement.name, text:statement.text, uid:statement.uid, timestamp:statement.timestamp}) 
CREATE (s)-[:BY {context:context.uid,timestamp:s.timestamp}]->(u) 
CREATE (s)-[:IN {user:u.id,timestamp:s.timestamp}]->(context)  
WITH u, s, context, statement 
FOREACH (conceptName in statement.uniqueconcepts |  
MERGE (c:Concept {name:conceptName}) ON CREATE SET c.uid=apoc.create.uuid() 
CREATE (c)-[:BY {context:context.uid,timestamp:s.timestamp,statement:s.suid}]->(u) 
CREATE (c)-[:OF {context:context.uid,user:u.uid,timestamp:s.timestamp}]->(s)  
CREATE (c)-[:AT {user:u.uid,timestamp:s.timestamp,context:context.uid,statement:s.uid}]->(context)  )  
WITH u, s 
UNWIND $conceptsRelations as conceptsRelation MATCH (c_from:Concept{name: conceptsRelation.from}) MATCH (c_to:Concept{name: conceptsRelation.to}) 
CREATE (c_from)-[:TO {context:conceptsRelation.context,statement:conceptsRelation.statement,user:u.uid,timestamp:conceptsRelation.timestamp, uid:apoc.create.uuid(), gapscan:conceptsRelation.gapscan, weight: conceptsRelation.weight}]->(c_to)  
RETURN DISTINCT s.uid

但是当我运行它时,出现此错误:

Neo.ClientError.Statement.TypeError
Property values can only be of primitive types or arrays thereof

有人知道为什么会这样吗?我的params似乎设置正确,我没看到它们不能以这种方式使用...谢谢!

2 个答案:

答案 0 :(得分:1)

问题出在这里:

...
FOREACH (conceptName in statement.uniqueconcepts |  
MERGE (c:Concept {name:conceptName})
...
参数中的

uniqueconcepts是对象列表,而不是字符串列表,因此,当尝试合并conceptName时,它会出错,因为conceptName不是基本类型(或数组或基本类型)。我认为您将要使用uniqueConcept而不是conceptName,在MERGE中使用name:uniqueConcept.name。检查statement.uniqueconcepts元素的其他用法。

答案 1 :(得分:0)

这个答案适用于其他像我这样的n00b,他们试图在不阅读友好手册的情况下将复合数据类型放入属性中,并得到上面的错误。 Google指向此处,因此我觉得应该添加此答案。

具体来说,我想将元组列表[(datetime, event), ...]存储到关系的属性中。

可能遇到的错误是:

Neo.ClientError.Statement.TypeError: Property values can only be of primitive types or arrays thereof

Neo.ClientError.Statement.TypeError: Neo4j only supports a subset of Cypher types for storage as singleton or array properties. Please refer to section cypher/syntax/values of the manual for more details.

Neo4j工作人员在this forum post中很好地总结了底线:

Neo4j不允许将地图作为属性(基本上不允许子属性),并且虽然允许将列表作为属性,但它们不能是地图列表(或与此相关的列表)。

基本上,我试图绕过数据库的自然功能。似乎有两种解决方法:

  1. 按照建议的here挖入脚跟,并将属性存储为例如JSON字符串

  2. 重新考虑设计,并将这些类型的属性建模到图中(即,对节点更具体)

经过重新思考,我想出了一个简单得多的数据模型,该模型不需要关系中的复合属性。尽管选项1可能有其用途,但是当我们不得不坚持设计良好的系统(neo4j )时,通常这表明我们应该改变路线。 安德烈斯