Neo4j - 根据端节点 sub class 类型区分关系

Neo4j - Discriminating relationships based on end node sub class type

我注意到,当在 spring-data-neo4j 4 数据模型中使用继承时,超级 class 被用作基于端节点类型加载和区分关系时的鉴别器。有什么办法可以强制 spring-data-neo4j-4 使用 subclass 作为鉴别器吗?

例如,假设我们有一个数据模型(class 图),左侧为下图,右侧为它的 neo4j 数据库表示。

目前,如果我们有一个所有者实体,其代码如下:

@NodeEntity
class Owner extends BaseNodeEntity {

    ...

    @Relationship(type="OWNS")
    private Set<Dog> dogs; // both dog and cat are mapped here

    @Relationship(type="OWNS")
    private Set<Cat> cats; // both dog and cat are mapped here

    ...
}

spring-data-neo4j-4 框架会自动将 Dog 和 Cat 映射到 Cats 集合和 Dogs 集合,所以我有两个 'dogs'(虽然一个其中一个实际上是一只猫),还有两个 'cats',(尽管其中一个实际上是一只狗)从数据库中加载。如果我从数据模型中删除超级 classes Pet 和 BaseNodeEntity,那么 Dog 和 Cat 会自动正确映射到它们各自的集合。

有没有办法强制 spring-data-neo4j-4 正确映射我的数据模型,或者我是否会被迫更改我的数据模型?我不想从我的数据模型中删除 super classes,因为我有很多重复使用,并添加额外的关系(即将 OWNS 拆分为 CAT_OWNER 和 DOG_OWNER ) 会同样烦人。

更新

我现在注意到此行为不一致。我写了一个测试映射的单元测试。奇怪的是,它有时通过,有时失败(有时它错误地将猫映射为狗,将狗映射为猫,有时却没有)。手动 运行 单元测试 10 次给了我以下通过/失败结果。

Run, Result (pass / fail)
1   P
2   F
3   F
4   P
5   F
6   P
7   F
8   F
9   P
10  F

当然映射行为应该是一致的。这可能是 SDN-4 中的错误吗?

2016 年 5 月 8 日更新

抱歉延迟更新。我刚刚有机会重新开始这个项目。我已经重新测试了这个,并且在最新的稳定版 neo4j 中得到了相同的结果。

<neo4j.version>2.3.2</neo4j.version>
<sdn.version>4.1.1.RELEASE</sdn.version>
<java.version>1.8</java.version>
<neo4j-ogm.version>2.0.1</neo4j-ogm.version>
<spring-data-commons.version>1.12.1.RELEASE</spring-data-commons.version>

我在下面附上了我们测试用例中使用的实际域模型。测试用例详情可见https://github.com/johndeverall/thescene-spa/issues/142。测试用例代码为:

    @Test
    public void saveAndLoadTags() { 
        log.info("Given we have a member with some events");
        Member member = createMember();
        Event event1 = eventService.createEvent("Event1", member);
        Event event2 = eventService.createEvent("Event2", member);

        log.info("When I tag my events with some tags");
        contentService.tag("Tag1", "", event1, member);
        contentService.tag("Tag1", "", event1, member); // should create no new tags or relationships
        contentService.tag("Tag2", "", event1, member);
        contentService.tag("Tag2", "", event2, member);

        log.info("Then my events should be appropriately tagged");
        event1 = eventService.loadEventBySceneId(event1.getSceneId());
        assertThat(event1.getTags().size(), is(equalTo(2)));
        assertThat(event2.getTags().size(), is(equalTo(1)));

        log.info("And I should have created two tags total");
        Iterator<Tag> iterator = contentService.getAllTags().iterator();
        List<Tag> tags = StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false).collect(Collectors.<Tag> toList());
        assertThat(tags.size(), is(equalTo(2)));

        log.info("And our member should have created two tags");
        member = memberService.loadMemberByEmailAddressPasswordAccount(emailAddress);

        // **************************************************************
        // member.getCreatedTags().size() more often than not returns 3   causing my test failure!
        // **************************************************************
        assertThat(member.getCreatedTags().size(), is(equalTo(2)));
    }

测试用例显示的问题

以下方法:

public Member loadMemberByEmailAddressPasswordAccount(String emailAddress) { 
        Filter filter = new Filter("email", emailAddress);
        Collection<EmailAddressPasswordAccount> emailAddressPasswordAccounts = session.loadAll(EmailAddressPasswordAccount.class, filter, 2);
        return emailAddressPasswordAccounts.isEmpty() ? null : emailAddressPasswordAccounts.iterator().next().getMember();
    }

Returns 一个 Member 对象,它有一组包含 2 个标签的 createdTags 和一个实际上是事件的标签。

我的实际领域模型如下(未简化为狗和猫):

附加信息:

我已经尝试使用@NodeEntity 注释对除BaseNodeEntity 之外的所有模型对象进行注释。属性已注释。

2016 年 5 月 9 日更新

如果我将 loadMemberByEmailAddressPasswordAccount 的 ogm 代码换成存储库上派生的查找器,我会得到相同的间歇性结果。

上面涉及具有相同类型但不同端节点类型的关系集合的案例是一个错误- http://github.com/neo4j/neo4j-ogm/issues/161

此问题已修复并可在 Neo4j OGM 2.0.2 中使用