Neo4j - 基于端节点子类类型区分关系

时间:2015-12-24 08:57:47

标签: neo4j spring-data-neo4j-4 neo4j-ogm

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

例如,假设我们左边有一个数据模型(类图),右边是neo4j数据库表示。

Class diagram and neo4j representation

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

@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,所以我有两只“狗”(虽然其中一只实际上是一只猫),和两个'猫',(虽然其中一个实际上是一只狗)从数据库加载。如果我从数据模型中删除超类Pet和BaseNodeEntity,那么Dog和Cat会自动映射到它们各自的集合。

有没有办法可以强制spring-data-neo4j-4正确映射我的数据模型,还是会被迫改变我的数据模型?我并不热衷于从我的数据模型中删除超类,因为我有很多重复使用,并且添加额外的关系(即将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();
    }

返回一个Member对象,该对象具有一组包含2个Tags的createdTags和一个实际上是Event的标记。

我的实际域名模型如下(未简化为Dogs and Cats):

OGM Diagram

其他信息:

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

2016年5月9日更新

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

1 个答案:

答案 0 :(得分:1)

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

这已得到修复,可在Neo4j OGM 2.0.2

中找到