在Neo4j中使用索引

时间:2016-12-08 20:09:33

标签: neo4j

假设我有两种类型的节点:服务器和:客户端。

(Client)-[:CONNECTED_TO]->(Server)

我想找到按年龄排序连接到某个服务器的女性客户端。

我做了这个

Match (s:Server{id:"S1"})<-[:CONNNECTED_TO]-(c{gender:"F"}) return c order by c.age DESC

执行此操作后,将遍历链接到“我的服务器”节点的所有客户端节点以查找最高年龄。 有没有办法在性别和年龄属性上索引客户端节点以避免完整扫描?

2 个答案:

答案 0 :(得分:2)

  1. 您可以在:Client(gender)上创建索引,如下所示:

    CREATE INDEX ON :Client(gender);
    

    但是,您的特定查询可能会从:Server(id)创建索引中受益更多,因为可能有很多女性客户,但可能只有一个Server具有该ID。所以,你可能想要这样做:

    CREATE INDEX ON :Server(id);
    

    但是,更好的是,如果每个Server都有一个唯一的id属性,您应该创建唯一性约束(它也会自动为您创建索引):

    CREATE CONSTRAINT ON (s:Server) ASSERT s.id IS UNIQUE;
    
  2. 目前,neo4j不使用索引来执行排序,但有一些APOC procedures支持它。但是,这些过程不支持按降序返回结果,这正是您想要的。因此,如果您确实需要为此目的使用索引,则解决方法是向minusAge节点添加额外的Client属性,其中包含age属性的负值。如果这样做,那么首先创建一个索引:

    CREATE INDEX ON :Client(minusAge);
    

    然后使用此查询:

    MATCH (s:Server{id:"S1"})<-[:CONNNECTED_TO]-(cl:Client {gender:"F"})
    CALL apoc.index.orderedRange('Client', 'minusAge', -200, 0, false, -1) YIELD node AS c
    RETURN c;
    

    该过程的第3个和第4个参数用于您要用于匹配的最小值和最大值(针对minusAge)。第5个参数应该是false用于您的目的(实际上当前被实现忽略)。最后一个参数用于LIMIT值,-1表示您不需要限制。

答案 1 :(得分:1)

如果这是您经常做的请求,那么您可能希望将该数据写出来。正如您所经历的那样,该查询可能非常昂贵,并且您获得的客户越多越好,因为事实上,必须检索所有连接的节点并进行属性检查/比较运行在他们身上。

作为解决方法,您可以在修改其年龄数据时向客户端添加其他连接。

作为建议,您可以创建Age节点并为最早的客户创建MATURE关系。

(:服务器)LT - [:CONNNECTED_TO] - (:客户机) - [:成熟] - GT;(:年龄)

您可以为所有年龄段执行此操作,并根据需要在Age节点(具有索引/唯一年龄属性)上运行查询。如果您有100,000个客户,但只对按年龄排序的前100名感兴趣,则无需获得所有客户并订购它们......这实际上取决于您的用例和客户端应用程序。

虽然这当然不是一个好的模式,但我已经看到它在生产中起作用,并且是我在不同生产环境中表现良好的唯一解决方法。

如果这个答案没有解决你的问题(我也很喜欢使用年龄属性),我希望它至少能让你知道下一步该怎么做。