Neo4j: не знаю, как отобразить граф на бин Spring Data - PullRequest
0 голосов
/ 19 сентября 2018

Я пишу приложение для захвата свойств конфигурации других приложений.Config - мой основной объект домена.Между Config объектами существуют иерархические отношения (один Config [: OVERRIDES] другой 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 для достижения моей цели?

ОБНОВЛЕНИЕ: я придумала аннотированный POJO для Config.Но когда я пытаюсь вернуть его в коде, properties всегда пусто вместе с parentConfig.

@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 голосов
/ 24 сентября 2018

Вы близки к решению, но в Neo4j-OGM есть техническое ограничение (библиотека, используемая в Spring Data Neo4j для отображения графа объектов): при использовании аннотации @Properties она сохраняется только с префиксом загрузки (по умолчанию)имя атрибута) с правым разделителем (по умолчанию .).Так что в основном в вашем случае он будет загружать только свойства с префиксом properties., а не все, которые возвращаются.

В Spring Data Neo4j также есть возможность предоставить @QueryResult, который можно рассматривать какDTO.Вы можете отметить промежуточный класс с аннотацией.Убедитесь, что этот класс также является частью вашего сканирования сущностей.

@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}}

Обратите внимание, что я написал тест с постоянством «оригинального» * ​​1016 * объекта, свойства которого сопоставлены, как вы выше, и я просто добавил их в префикс 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 Здесьэто ссылка на документацию для конвертеров, и вы должны реализовать CompositeAttributeConverter.

Neo4j-OGM не предназначен для постоянной работы с изменением имени свойства, и это также будет сложнорешить, что сохранить, если свойство с nameA существует в самом классе домена и также определено в такой карте свойств.

...