[英]How to add labels dynamically to nodes in Neo4j from neo4j-ogm or spring-data-neo4j?
[英]How to dynamically change entity types in neo4j-ogm or spring-data-neo4j?
关于“如何向Neo4j中的节点动态添加标签”存在一个问题。 有没有办法动态更改实体类型?
举个例子:
@NodeEntity
public class User {
@Properties(prefix = "custom")
private Map userProperties;
}
从https://neo4j.com/blog/spring-data-neo4j-5-0-release/看,我可以创建动态属性。 运行时也可以有动态类型吗? 我想在需要时动态地将“用户”类型更改为“消费者” /“管理员” /“生产者”。 实体类型不是穷举性的。
提前致谢! :)
除了来自类和接口的主要类型外,在Set<String>
上还有一个@Labels
注释,该注释被存储/管理。
参见: https : //docs.spring.io/spring-data/neo4j/docs/current/reference/html/#reference : annotating-entities : node-entity : runtime-managed-labels
@Labels
机制很棒,对于许多用例来说,这是我要说的最佳解决方案。
如果您想从存储库中退出另一个类,则确实需要做更多的工作。
我正在音乐相关项目中进行此操作。 我有Artist
(不是抽象的,完全可以用于不知道是否是乐队的任何事物),还有从Artist扩展来的Band
和SoloArtist
,带有其他标签:
@NodeEntity
public class Artist {}
@NodeEntity
public class Band extends Artist{}
在自定义存储库扩展中,我所知道的是:
interface ArtistRepository<T extends Artist> extends Repository<T, Long>, ArtistRepositoryExt {
Optional<T> findOneByName(String name);
// Specifying the relationships is necessary here because the generic queries won't recognize that
// Band has a relationship to country that _should_ be loaded with default depth of 1.
@Query("MATCH (n:Artist) WITH n MATCH p=(n)-[*0..1]-(m) RETURN p ORDER BY n.name")
List<T> findAllOrderedByName();
@Query("MATCH (n:Artist) WHERE id(n) = $id WITH n MATCH p=(n)-[*0..1]-(m) RETURN p")
Optional<T> findById(@Param("id") Long id);
<S extends T> S save(S artist);
}
interface ArtistRepositoryExt {
Band markAsBand(Artist artist);
SoloArtist markAsSoloArtist(Artist artist);
}
class ArtistRepositoryExtImpl implements ArtistRepositoryExt {
private static final String CYPHER_MARK_AS_BAND = String.format(
"MATCH (n) WHERE id(n) = $id\n" +
"OPTIONAL MATCH (n) - [f:BORN_IN] -> (:Country)\n" +
"REMOVE n:%s SET n:%s\n" +
"DELETE f",
SoloArtist.class.getSimpleName(),
Band.class.getSimpleName());
private static final String CYPHER_MARK_AS_SOLO_ARTIST = String.format(
"MATCH (n) WHERE id(n) = $id\n" +
"OPTIONAL MATCH (n) - [f:FOUNDED_IN] -> (:Country)\n" +
"REMOVE n:%s SET n:%s\n" +
"DELETE f",
Band.class.getSimpleName(),
SoloArtist.class.getSimpleName());
private final Session session;
public ArtistRepositoryExtImpl(Session session) {
this.session = session;
}
@Override
public Band markAsBand(Artist artist) {
session.query(CYPHER_MARK_AS_BAND, Map.of("id", artist.getId()));
// Needs to clear the mapping context at this point because this shared session
// will know the node only as class Artist in this transaction otherwise.
session.clear();
return session.load(Band.class, artist.getId());
}
@Override
public SoloArtist markAsSoloArtist(Artist artist) {
session.query(CYPHER_MARK_AS_SOLO_ARTIST, Map.of("id", artist.getId()));
// See above
session.clear();
return session.load(SoloArtist.class, artist.getId());
}
}
尽管这很简洁,但在更深层的嵌套类场景中,我会做出努力的想法。 另外,如果您想以多态方式使用存储库,请按照我的意愿重新声明派生的finder方法。
我也保留专用存储库。
如果这个问题仍然与您有关,请告诉我是否也对您有用。 您将在这里找到整个项目:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.