2016-07-05 3 views
0

Я использую Spring Data Neo4j 4. Допустим, у меня есть узлы типа лица и соответствующий объект домена Java являетсяСвязанные узлы того же типа с SDN

@NodeEntity 
public class Person { 

    @GraphId private Long id; 

    private String name; 

    private String lastName; 

    @Relationship(type = "KNOWS") 
    Set<Person> myTypes; 


} 

И я пытаюсь создать график как `

Джон-KNOWS-> Джордж и Джон-KNOWS- > Ann. Ann-KNOWS-> Dug

`. Ниже показано, как я настраиваю объекты домена и сохраняю.

Person john = new Person("John","P"); 
    Person george = new Person("George","B"); 
    Person Ann = new Person("Ann","M"); 
    Person Dug = new Person("Dug","S"); 
    Set<Person> Persons= new HashSet<Person>(); 
    Set<Person> Persons1= new HashSet<Person>(); 
    Persons1.add(Dug); 
    Ann.setMyTypes(Persons1); 
    Persons.add(george); 
    Persons.add(Ann); 
    john.setMyTypes(Persons); 

    personRepository.save(john); 
    personRepository.save(george); 
    personRepository.save(Ann); 
    personRepository.save(Dug); 

Но, к моему удивлению, только узлы создаются без связей. Я отлаживал это и после этой строки personRepository.save (john) Узлы со связями создавались, но во время последующего сохранения все отношения были удалены. Ниже приведено то, что напечатано в журналах, и ясно сказано, что отношения удалены.

Request: UNWIND {rows} as row CREATE (n:`Person`) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, row.type as type with params {rows=[{nodeRef=-2115049587, type=node, props={name=George, attrib=B}}, {nodeRef=-341599918, type=node, props={name=Ann, attrib=M}}, {nodeRef=-737678933, type=node, props={name=John, attrib=P}}, {nodeRef=-1025122203, type=node, props={name=Dug, attrib=S}}]} 
Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MERGE (startNode)-[rel:`KNOWS`]->(endNode) RETURN row.relRef as ref, ID(rel) as id, row.type as type with params {rows=[{relRef=-1807300324, endNodeId=2448, type=rel, startNodeId=2450}, {relRef=-272508006, endNodeId=2451, type=rel, startNodeId=2449}, {relRef=-845107952, endNodeId=2449, type=rel, startNodeId=2450}]} 
Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`KNOWS`]->(endNode) DELETE rel with params {rows=[{endNodeId=2448, startNodeId=2450}]} 
Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`KNOWS`]->(endNode) DELETE rel with params {rows=[{endNodeId=2449, startNodeId=2450}]} 
Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`KNOWS`]->(endNode) DELETE rel with params {rows=[{endNodeId=2451, startNodeId=2449}]} 

Не знаете, где я неправильно или это, как предполагается работать

ответ

0

Я думаю, что проблема с тем, как вы сохраняете объекты Person. Одним из решений было бы сначала сохранить объекты человека. Затем добавьте отношения и сохраните единственные объекты, в которые вы добавили отношения, а не добавленные объекты.

Для примера

Person john = new Person("John","P"); 
    Person Ann = new Person("Ann","M"); 

    Set<Person> Persons= new HashSet<Person>(); 
    Persons.add(Ann); 
    john.setMyTypes(Persons); 
    personRepository.save(john); 

выше сэкономит Джон и Энн, а также создаст отношения «ЗНАЕТ» между ними. Не нужно снова спасать Энн.

Если попытаться снова сохранить Энн, после кода выше

personRepository.save(Ann); 

отношения будут получать удалены Neo4j будет видеть его как объект, который не имеет никакого отношения, как отношения не был там, когда Энн объект был создан ранее

2

Это случай, когда отношения являются двусмысленными для OGM, потому что они существуют между одним и тем же типом, но в определенном направлении.

(john)-[:KNOWS]->(george) также подразумевает, что у Джорджа должны быть входящие отношения от Джона, но модель домена не отражает это. При последующих сохранениях, как вы заметили, отношения удаляются, потому что картограф не может понять, что нужно сохранить из-за двусмысленности.

Если у вас есть такие отношения между объектами одного и того же типа, явное определение направления отношений является решением. В вашем случае отношения от одного человека к другому всегда находятся в исходящем направлении, поэтому добавление такого направления позволяет понять, что OGM не беспокоится о входящих отношениях одного типа.

@Relationship(type = "KNOWS", direction = "OUTGOING") 
Set<Person> myTypes; 

Кроме того, вы не должны экономить каждый человек- в вашем примере, сэкономив John достаточно, потому что OGM может пройти от Джона Джорджа и Энн и, следовательно, Dug.

+0

Спасибо. Но выше всего лишь простой вариант. Я занимаюсь импортом данных из огромного файла excel, и если мне нужно выяснить, что сохранить, а что не экономить, сама по себе становится огромной задачей. Во-вторых, во многих случаях я не знаю направления отношений перед раздачей. Есть ли способ указать направление во время выполнения? Ниже в сообщении говорится, что мы не можем http://stackoverflow.com/questions/18517000/dynamicrelationshiptype-in-spring-data-neo4j-or-defining-relationship-types-at-r –

+1

Нет, вы не можете указывать маршруты во время выполнения с SDN/OGM. OGM не может быть подходящим инструментом для работы, то есть импорт из excel – Luanne