neo4j - 如何只匹配前n个关系

时间:2013-04-25 13:04:24

标签: neo4j cypher

除了稍后在LIMIT n上过滤之外,是否有一种默认方式如何只匹配前n个关系?

我有这个问题:

START n=node({id})
MATCH n--u--n2
RETURN u, count(*) as cnt order by cnt desc limit 10;

但假设n--u关系的数量非常高,我想放宽此查询并采用前100个随机关系,而不是继续u--n2...

这是一个协作过滤任务,假设用户更相似,我不想匹配所有用户u,而是一个随机子集。这种方法应该在性能上更快 - 现在我有~500ms的查询时间但是想要将其降低到50ms以下。

我知道我可以将上面的查询分成两个独立的查询,但仍然在第一个查询中它会通过所有用户,而后来它会限制输出。我想在match阶段限制最大相对数。

2 个答案:

答案 0 :(得分:2)

您可以使用WITH,然后LIMIT初始结果来管道查询的当前结果,然后在同一查询中继续:

START n=node({id})
MATCH n--u
WITH u
LIMIT 10
MATCH u--n2
RETURN u, count(*) as cnt 
ORDER BY cnt desc 
LIMIT 10;

上面的查询将为您找到前10个u,然后继续查找前10个匹配的n2

或者,您可以暂停第二个LIMIT,您将获得所有匹配n2的前十个u(意味着您可以拥有如果它们与前10个u匹配,则返回超过10行。

答案 1 :(得分:1)

这不是你问题的直接解决方案,但由于我遇到了类似的问题,我的解决方案对你来说可能很有趣。

我需要做的是:通过索引获取关系(可能会产生数千个)并获取这些关系的起始节点。由于起始节点始终与索引查询相同,因此我只需要第一个关系的startnode。

由于我无法通过cypher实现这一点(ean5533提出的查询效果不佳),我使用的是简单unmanaged extensionnice template)。

@GET
@Path("/address/{address}")
public Response getUniqueIDofSenderAddress(@PathParam("address") String addr, @Context GraphDatabaseService graphDB) throws IOException
{
    try {
        RelationshipIndex index = graphDB.index().forRelationships("transactions");
        IndexHits<Relationship> rels = index.get("sender_address", addr);

        int unique_id = -1;
        for (Relationship rel : rels) {
            Node sender = rel.getStartNode();
            unique_id = (Integer) sender.getProperty("unique_id");
            rels.close();
            break;
        }

        return Response.ok().entity("Unique ID: " + unique_id).build();
    } catch (Exception e) {
        return Response.serverError().entity("Could not get unique ID.").build();
    }
}

对于这种情况,加速非常好。

我不知道您的确切用例,但由于Neo4j甚至支持HTTP流式传输,您应该能够创建将您的查询转换为非托管扩展并仍然获得完整性能。 例如,“java-querying”所有符合条件的节点,并将部分结果发送到HTTP流。