Neo4j:不知道如何将图形映射到Spring Data bean

时间:2018-09-19 18:42:35

标签: neo4j spring-data spring-data-neo4j

我正在编写一个应用程序以捕获其他应用程序的配置属性。 Config是我的主要域对象。 Config对象之间存在层次关系(一个Config [:覆盖另一个Config)。因此,给定最底端的Config,我需要将层次结构一直推到最顶端的Config,并沿途收集Config对象的所有属性,并将它们合并为一个最后Config。但是我不知道如何使用Spring Data做到这一点。

这是2个Config对象的架构:

CREATE (c1:Config {name:'ConfigParent'});
SET c2.docker_tag='1.0.0';
SET c2.mem_limit='1gb';

MATCH (c1:Config {name: 'ConfigParent'}) 
CREATE (c2:Config {name:'ConfigChild'})-[:OVERRIDES]->(c1)
SET c2.docker_tag='1.0.1';

ConfigChild属性需要与ConfigParent合并,并且ConfigParent中所有重复的属性都将被覆盖。所以我最后的属性应该是:

name='ConfigMerged'  //I don't know what this name would be?
docker_tag='1.0.1'
mem_limit='1gb'

Config中可以有任何键/值对,因此不能按名称返回它们。我想出了我想做的CQL:

MATCH p = SHORTESTPATH((c2:Config)<-[:OVERRIDES*]-(c1:Config)) 
WHERE c1.name = 'ConfigChild' and not (c2)-[:OVERRIDES]->() 
UNWIND NODES(p) as props return PROPERTIES(props);

JSON响应如下所示:

[
  {
    "keys": [
      "properties(props)"
    ],
    "length": 1,
    "_fields": [
      {
        "name": "ConfigParent",
        "docker_tag": "1.0.0",
        "mem_limit": "1gb"
      }
    ],
    "_fieldLookup": {
      "properties(props)": 0
    }
  },
  {
    "keys": [
      "properties(props)"
    ],
    "length": 1,
    "_fields": [
      {
        "name": "ConfigChild",
        "docker_tag": "1.0.1"
      }
    ],
    "_fieldLookup": {
      "properties(props)": 0
    }
  }
]

问题是,我不知道如何将其映射到POJO。我需要一个Config域对象还是一个Properties域对象?这是实现我的目标的最佳CQL吗?

更新:我为Config提出了一个带注释的POJO。但是当我尝试用代码返回它时,propertiesparentConfig总是空的。

@NodeEntity
public class Config {

    @Id 
    @GeneratedValue 
    private Long id;

    @Relationship(type = "OVERRIDES")
    private Config parentConfig;

    @Properties(allowCast=true)
    private Map<String, String> properties;

    ....
}

这是我正在测试的基本查询,只是为了查看是否可以映射到POJO:

 @Query("MATCH (c1:Config) RETURN c1;")
 List<Config> findConfigAny(@Param("configName") String configName);

1 个答案:

答案 0 :(得分:1)

您已接近解决方案,但Neo4j-OGM(Spring Data Neo4j中用于对象图映射的库)存在技术限制:使用@Properties批注时,它将仅保留并加载前缀(默认属性名称)带有右定界符(默认.)。因此,基本上,在您的情况下,它只会加载以properties.为前缀的属性,而不会加载所有返回的属性。

在Spring Data Neo4j中,还可以提供可以视为DTO的@QueryResult。您可以使用注释标记中间类。请确保此类也属于您的实体扫描。

@QueryResult
public class ConfigDto {

  private String name;

  private Map<String, String> properties;

}

如果您还将SDN信息库方法的返回类型也更改为此类型

@Query("MATCH p = SHORTESTPATH((c2:Config)<-[:OVERRIDES*]-(c1:Config))"
 + " WHERE c1.name = 'Child' and not (c2)-[:OVERRIDES]->()"
 + " UNWIND NODES(p) as props return props.name as name, PROPERTIES(props) as properties")
List<ConfigDto> configs();

与使用此方法相比,它将返回:

ConfigDto{name='Child', properties={a.exclusive=1, name=parentConfig, a.override=parent value}}
ConfigDto{name='Child', properties={a.exclusiveChild=my value, name=Child, a.override=child value}}

请注意,我编写了一个具有“原始” Config对象持久性的测试,该对象具有上面所映射的属性,而我只是在它们之前加上了a.。您可以看到该名称也在查询返回的属性映射中,因此该映射包含节点的所有属性。

编辑(保存评论中的内容) 通过上述解决方案,可以从Neo4j加载现有数据。

除了@Properties解决方案之外,不可能保留任意属性,但这将在图形中创建“前缀”,“定界”属性。例如。输入代码中的问题,您将得到properties.docker_tag

例如,您可以为Map编写自己的属性转换器,然后定向并从https://github.com/neo4j/neo4j-ogm/blob/master/core/src/main/java/org/neo4j/ogm/typeconversion/MapCompositeConverter.java中吸取一些想法。 这是转换器的documentation的链接,您应该实现CompositeAttributeConverter

Neo4j-OGM并非总是用于更改属性名称,并且如果在域类本身中存在带有nameA的属性,并且在该属性中进行定义,那么决定保存内容也将很复杂。物业地图。

相关问题