在计算

时间:2017-05-05 16:00:02

标签: neo4j spring-data-neo4j-4

我尝试使用neo4j和spring数据对一百万个对象进行分页。我的程序执行两个查询: 第一个匹配数据。第二个计算所有符合我限制的元素。但最后一次查询需要花费很多时间。

这是paginate函数的一部分:

 @Autowired
Neo4jOperations template;`


StringBuilder query = new StringBuilder(" match (n:Domain) where n.isPrincipale={isPrincipale} ");
mapOfVars.put("isPrincipale", true);
  if (request.getParameterMap().containsKey("mydom")
      && !request.getParameter("mydom").isEmpty()) {
            query.append(" and n.domain  =~ {mydom}");
            mapOfVars.put("mydom",".*(?i)"+request.getParameter("mydom")+".*");
}

问题在这里:

iTotalRecords = Integer.valueOf((template.query(query.toString() + " return count(n) as count", mapOfVars)).queryResults().iterator().next().get("count").toString());

计数后我得到匹配的结果:

query.append(" 
     return n.domain as domain, n.hasDmarc as dmarc , 
     n.spf_action    as spf, n.updatedAt as updatedAt , 
     n.existValue as exst , id(n) as id 
     skip  {start} limit {displayCount}");
 mapOfVars.put("start", iDisplayStart);
 mapOfVars.put("displayCount", iDisplayCount);

Iterable<Map<String, Object>> domains = template.query(query.toString(), mapOfVars);

1 个答案:

答案 0 :(得分:2)

如果:Domain(isPrincipale)上没有索引(或唯一性约束),则neo4j必须扫描所有Domain个节点才能找到匹配的节点。

要创建索引,请运行以下查询:

CREATE INDEX ON :Domain(isPrincipale);

但请注意,如果只有相对较小百分比的相同标记节点具有您想要匹配的isPrincipale值,那么使用索引会有所帮助。不幸的是,由于isPrincipale值是一个布尔值(因此只有两个可能的值),索引可能没什么用。

[UPDATE]

主要问题是,您正在执行完整查询,以便每次获取所有匹配的Domain个节点(在计算它们时以及在每个分页步骤中)。这显然非常昂贵。获得所有匹配节点然后在本地进行计数和分页会更好(速度方面)。

另一种加快速度的方法(但可能比上面的程度更小)是消除昂贵的正则表达式字符串比较以找到匹配的Domain节点。如果您事先知道可能的mydom字符串集,则可以只存储这些字符串与数据库中相应Domain个节点之间的关系。例如,您可以创建DomainName个节点,并在每个节点和相应的HAS_DOMAIN节点之间创建Domain个关系。这样,您的第一个代码段可能会变成这样,并导致更快的查询:

@Autowired
Neo4jOperations template;`

StringBuilder query = new StringBuilder();
String mydom = request.getParameter("mydom");
if (mydom != null && !mydom.isEmpty()) {
  query.append("MATCH (:DomainName {name: $mydom})-[:HAS_DOMAIN]->(n:Domain) ");
  mapOfVars.put("mydom", mydom);
} else {
  query.append("MATCH (n:Domain) ");
}
query.append("WHERE n.isPrincipale=$isPrincipale")
mapOfVars.put("isPrincipale", true);