我尝试使用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);
答案 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);