现状
使用 springboot ogm 访问 neo4j。
结果报错:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.neo4j.ogm.exception.MappingException: Error mapping GraphModel to instance of com.knowledgeGraph.kgClient.domain.Movie
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
Caused by: org.neo4j.ogm.exception.AmbiguousBaseClassException: Multiple classes found in type hierarchy that map to: [Person, Actor, Director]
at org.neo4j.ogm.MetaData.resolve(MetaData.java:174) ~[neo4j-ogm-core-2.0.1.jar:na]
at org.neo4j.ogm.annotations.EntityFactory.resolve(EntityFactory.java:121) ~[neo4j-ogm-core-2.0.1.jar:na]
at org.neo4j.ogm.annotations.EntityFactory.instantiateObjectFromTaxa(EntityFactory.java:105) ~[neo4j-ogm-core-2.0.1.jar:na]
at org.neo4j.ogm.annotations.EntityFactory.newObject(EntityFactory.java:61) ~[neo4j-ogm-core-2.0.1.jar:na]
原因
原因:使用 ogm 中 loadAll 等方法,虽然指定了 class 类,这时候 label 唯一。但是 neo4j 中的数据有多个 label,导致 ogm 报错。
代码分析
原因:spring data neo4j 的 MetaData.resolve (String... taxa)
方法会根据标签去找对应的java节点类(如根据”Company“标签找到Company.java类)。
当传入taxa参数超过一个时,他会去判断多个标签之间是不是父子关系,如果不是父子关系就放入Set<ClassInfo> resolved
中,如果是父子关系,只保留子类。
但是最终他会判断resolved的size,如果>1就报错。
if (resolved.size() > 1) {
// Sort so we always get the same order
String[] sorted = Arrays.copyOf(taxa, taxa.length);
Arrays.sort(sorted);
throw new AmbiguousBaseClassException(Arrays.toString(sorted));
}
吐槽
其实这个是非常坑的,感觉明明可以优化。
解决方式
1)看是否存在脏数据,如果是脏数据可以把数据删除掉。
2)使用原生的 sql 自己查询构建结果,这种最保险。
多标签实体
查询方式
match (n:Person:Girl) return n
这样写,可以同时返回包含 Person 和 Girl label 的数据节点。
neo4j 如何更新节点的 label?
有时候 发现节点的 label 名字起错了怎么修改呢?!
一个节点是可以有多个 label 的 ,它的 labels 是一个列表。
查看节点的 label 可以用 labels(n) 命令。
所以,想要修改节点的 label ,可以先新加 label ,再删除旧的的label
match (n:CAR) set n:NEW remove n:CAR
match(n:NEW) RETURN labels(n)
参考资料
chat
https://stackoverflow.com/questions/66522758/the-neo4j-cypher-shell-and-the-browser-connections-are-working-but-the-golang-cl
https://cloud.tencent.com/developer/ask/sof/1841947
https://blog.csdn.net/wuxiaoyi1983/article/details/126773623