在 Spring 引导中加载具有最近邻居的 neo4j 节点
Loading neo4j nodes with nearest neighbours in Spring boot
在我的项目中,object User
有 collection 个 Item
项,与 one-to-many "OWNS" 关系。每一个项目
与具有 one-to-one "OWNED_BY" 关系的用户相关。
我的(缩短)类 看起来像这样:
@NodeEntity
public class User {
. . .
@Relationship(type="OWNS", direction = Relationship.OUTGOING)
private Collection<Item> items;
. . .
}
@NodeEntity
public class Item {
. . .
@Relationship(type="OWNED_BY", direction = Relationship.OUTGOING)
public User owner;
. . .
}
我使用用户和项目存储库存储节点
(示例):
@Repository
@Transactional
public interface UserRepository extends Neo4jRepository<User, Long> {
. . .
@Query("MATCH (user:User) WHERE ID(user)={0} RETURN user")
User getById(Long id);
. . .
}
只需用 setter 填充 Collection 并使用默认 save()
方法保存。
User user = ...
user.setItems(. . .);
userRepository.save(user);
一切正常。数据连同所有对应关系一直存在于图中。
Spring 数据文档指出“默认情况下,加载一个实例
将映射 object 的简单属性及其 immediately-related objects(即深度 = 1)。”
这正是我想要的。
然而,当我尝试取回数据时,这并没有发生。
获取用户使用:
User user = userRepository.getById(id);
确实 return 正确的用户,但它与项目(Collection 项目)的关系为空。
作为旁注,我正在使用 spring 引导,我的依赖项是这些:
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-neo4j:2.0.3.RELEASE')
//compile('org.springframework.data:spring-data-neo4j:5.0.8.RELEASE')
compile('org.neo4j:neo4j:3.4.3')
compile('org.neo4j:neo4j-ogm-core:3.1.0')
runtime('org.neo4j:neo4j-ogm-http-driver:3.1.0')
compile('org.springframework.boot:spring-boot-starter-mail:2.0.3.RELEASE')
compile('org.springframework.boot:spring-boot-starter-security:2.0.3.RELEASE')
compile('org.springframework.boot:spring-boot-starter-thymeleaf:2.0.3.RELEASE')
compile('org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-web:2.0.3.RELEASE')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.springframework.security:spring-security-test')
testCompile('org.mockito:mockito-core:2.7.22')
compile('junit:junit:4.12')
}
为什么会这样?加载给定节点时如何获取所有直接邻居(加载深度=1,这应该是默认值)?
编辑:我已经退回到使用提供的 Neo4jRepository findById(id, depth) 但我仍然无法弄清楚如何让它与我自己的查询一起使用。
使用自定义查询时,您无法真正从 Spring 添加深度。
而是在自定义查询本身中包含深度。
例如,假设您有一个消息链接列表:
(:Message{id:1})-[:NEXT]->(:Message{id:2})-[:NEXT]->(:Message{id:3})
\
\-[:ATTACHMENT]->(:Image{id:4})
您可以通过指定所需的根节点以及路径长度来获得最近的邻居,如下所示:
MATCH (m:Message)-[*0..0]-(a) where ID(m)=1 RETURN *
以上将return只有根节点。
MATCH (m:Message)-[*0..1]-(a) where ID(m)=1 RETURN *
MATCH (m:Message)-[*0..2]-(a) where ID(m)=1 RETURN *
以上将return:
(:Message{id:1})-[:NEXT]->(:Message{id:2})
和
(:Message{id:1})-[:NEXT]->(:Message{id:2})-[:NEXT]->(:Message{id:3})
\
\-[:ATTACHMENT]->(:Image{id:4})
分别
将您的查询修改为如下所示:
@Query("MATCH (user:User)-[p:OWNS*0..1]->(item:Item) WHERE user.username={0} RETURN *")
User getByUsernameWithItems(String username);
以上将 return 用户和 Collection<Item> items
将填充第一级相邻项目节点。
在我的项目中,object User
有 collection 个 Item
项,与 one-to-many "OWNS" 关系。每一个项目
与具有 one-to-one "OWNED_BY" 关系的用户相关。
我的(缩短)类 看起来像这样:
@NodeEntity
public class User {
. . .
@Relationship(type="OWNS", direction = Relationship.OUTGOING)
private Collection<Item> items;
. . .
}
@NodeEntity
public class Item {
. . .
@Relationship(type="OWNED_BY", direction = Relationship.OUTGOING)
public User owner;
. . .
}
我使用用户和项目存储库存储节点 (示例):
@Repository
@Transactional
public interface UserRepository extends Neo4jRepository<User, Long> {
. . .
@Query("MATCH (user:User) WHERE ID(user)={0} RETURN user")
User getById(Long id);
. . .
}
只需用 setter 填充 Collection 并使用默认 save()
方法保存。
User user = ...
user.setItems(. . .);
userRepository.save(user);
一切正常。数据连同所有对应关系一直存在于图中。 Spring 数据文档指出“默认情况下,加载一个实例 将映射 object 的简单属性及其 immediately-related objects(即深度 = 1)。” 这正是我想要的。 然而,当我尝试取回数据时,这并没有发生。
获取用户使用:
User user = userRepository.getById(id);
确实 return 正确的用户,但它与项目(Collection 项目)的关系为空。
作为旁注,我正在使用 spring 引导,我的依赖项是这些:
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-neo4j:2.0.3.RELEASE')
//compile('org.springframework.data:spring-data-neo4j:5.0.8.RELEASE')
compile('org.neo4j:neo4j:3.4.3')
compile('org.neo4j:neo4j-ogm-core:3.1.0')
runtime('org.neo4j:neo4j-ogm-http-driver:3.1.0')
compile('org.springframework.boot:spring-boot-starter-mail:2.0.3.RELEASE')
compile('org.springframework.boot:spring-boot-starter-security:2.0.3.RELEASE')
compile('org.springframework.boot:spring-boot-starter-thymeleaf:2.0.3.RELEASE')
compile('org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-web:2.0.3.RELEASE')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.springframework.security:spring-security-test')
testCompile('org.mockito:mockito-core:2.7.22')
compile('junit:junit:4.12')
}
为什么会这样?加载给定节点时如何获取所有直接邻居(加载深度=1,这应该是默认值)?
编辑:我已经退回到使用提供的 Neo4jRepository findById(id, depth) 但我仍然无法弄清楚如何让它与我自己的查询一起使用。
使用自定义查询时,您无法真正从 Spring 添加深度。 而是在自定义查询本身中包含深度。 例如,假设您有一个消息链接列表:
(:Message{id:1})-[:NEXT]->(:Message{id:2})-[:NEXT]->(:Message{id:3})
\
\-[:ATTACHMENT]->(:Image{id:4})
您可以通过指定所需的根节点以及路径长度来获得最近的邻居,如下所示:
MATCH (m:Message)-[*0..0]-(a) where ID(m)=1 RETURN *
以上将return只有根节点。
MATCH (m:Message)-[*0..1]-(a) where ID(m)=1 RETURN *
MATCH (m:Message)-[*0..2]-(a) where ID(m)=1 RETURN *
以上将return:
(:Message{id:1})-[:NEXT]->(:Message{id:2})
和
(:Message{id:1})-[:NEXT]->(:Message{id:2})-[:NEXT]->(:Message{id:3})
\
\-[:ATTACHMENT]->(:Image{id:4})
分别
将您的查询修改为如下所示:
@Query("MATCH (user:User)-[p:OWNS*0..1]->(item:Item) WHERE user.username={0} RETURN *")
User getByUsernameWithItems(String username);
以上将 return 用户和 Collection<Item> items
将填充第一级相邻项目节点。