具有大数据集的Spring数据/ Neo4j路径长度

时间:2013-08-06 18:33:05

标签: java neo4j spring-data spring-data-neo4j

我一直在运行以下查询,以查找给定人员某个“距离”内的亲属:

@Query("start person=node({0}), relatives=node:__types__(className='Person') match p=person-[:PARTNER|CHILD*]-relatives where LENGTH(p) <= 2*{1} return distinct relatives")
Set<Person> getRelatives(Person person, int distance);

2 * {1}来自于人们被表示为两个节点之间的一个概念上的“跳跃” - 一个人和一个伙伴关系。

到目前为止,测试人群一直很好。现在我转向实际数据,其中包括1-10百万的大小,这是永远的(也来自Web界面中的数据浏览器)。

假设成本是将所有内容加载到ancestors,我在数据浏览器中将查询重写为测试:

start person=node(385716) match p=person-[:PARTNER|CHILD*1..10]-relatives where relatives.__type__! = 'Person' return distinct relatives

在同一个数据存储中,它可以在几分之一秒内正常工作。但是当我想把它放回Java时:

@Query("start person=node({0}) match p=person-[:PARTNER|CHILD*1..{1}]-relatives where relatives.__type__! = 'Person' return relatives")
Set<Person> getRelatives(Person person, int distance);

这不起作用:

[...]
Nested exception is Properties on pattern elements are not allowed in MATCH.
"start person=node({0}) match p=person-[:PARTNER|CHILD*1..{1}]-relatives where relatives.__type__! = 'Neo4jPerson' return relatives"
                                         ^

有没有更好的方法在那里设置路径长度限制?我宁愿不使用where,因为这将涉及加载所有路径,可能加载数百万个节点,我只需要深度为10。这可能会让我没有更好的。

任何想法都将不胜感激!


迈克尔救了!

我的解决方案:

public Set<Person> getRelatives(final Person person, final int distance) {

    final String query = "start person=node(" + person.getId() + ") "
        + "match p=person-[:PARTNER|CHILD*1.." + 2 * distance + "]-relatives "
        + "where relatives.__type__! = '" + Person.class.getSimpleName() + "' "
        + "return distinct relatives";

    return this.query(query);

    // Where I would previously instead have called 
    // return personRepository.getRelatives(person, distance);
}

public Set<Person> query(final String q) {

    final EndResult<Person> result = this.template.query(q, MapUtil.map()).to(Neo4jPerson.class);
    final Set<Person> people = new HashSet<Person>();

    for (final Person p : result) {
        people.add(p);
    }

    return people;
}

哪个运行得非常快!

1 个答案:

答案 0 :(得分:1)

你快到了:)

您的第一个查询是一个完整的图形扫描,它有效地将整个数据库加载到内存中,并通过此模式匹配多次拉出所有节点。

所以它不会很快,也会返回庞大的数据集,不知道这是不是你想要的。

第二个查询看起来不错,唯一的问题是你不能参数化可变长度关系的最小值 - 最大值。由于查询优化/缓存的影响。

因此,现在您必须在repo中使用template.query()或不同的查询方法来获取不同的最大值。