返回Neo4j中每个查询的前n个结果

时间:2015-10-02 12:25:08

标签: neo4j cypher

我一直试图在密码查询中写入以下任务,但我没有得到正确的结果。其他stackoverflow问题讨论限制或收集,但我认为这不足以完成以下任务。

任务: 我有(p:Product)节点,在两个产品节点之间有一个名为" BOUGHT_TOGETHER"的关系。那是

(p:Product)-[b:BOUGHT_TOGETHER]-(q:Product)

关系b有一个名为" size"其中包含一些数字。我想返回按大小排序的每个产品关系的前3个结果。例如,查询结果应如下所示。

+------------------------+
| p.id  | q.id | b.size      |
+------------------------+
   1      2      10
   1      3       8
   1      5       7
   2      21      34
   2      17      20
   2      35      15
   3      5       49
   3      333     30
   3       65      5
   .       .       .
   .       .       .
   .       .       .

有人可以告诉我如何编写密码查询以达到预期效果吗?谢谢!

3 个答案:

答案 0 :(得分:5)

另一个解决方案是首先对关系进行排序,将它们在一个集合中进行管道处理,然后UNWIND只收集集合的3个第一个结果:

MATCH (p:Product)-[r:BOUGHT_TOGETHER]->(:Product)
WITH p, r
ORDER BY r.size DESC 
WITH p, collect(r) AS bts 
UNWIND bts[0..3] AS r
RETURN p.uuid as pid, endNode(r).uuid as qid, r.size as size

此处的测试控制台:http://console.neo4j.org/r/r88ijn

注意:在重新阅读jjaderberg的答案后,这有点类似,我觉得更具可读性。为什么我投票给他答案。

答案 1 :(得分:2)

Cypher有LIMIT和ORDER声明 http://neo4j.com/docs/stable/query-limit.html
http://neo4j.com/docs/stable/query-order.html

try {
            BufferedReader br = new BufferedReader(new FileReader("./data/countries.txt"));
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line + '\n');
            }
            br.close();

            ArrayList<String> tableRows = new ArrayList<String>();
            Pattern p = Pattern.compile(" <tr>(\\w+)</tr> ", Pattern.MULTILINE);
            Matcher m = p.matcher(sb);
            while (m.find()) {
                System.out.println("match");//it never prints thus there are no matches
                tableRows.add(m.group());
            }
            System.out.println(tableRows.size());//THE SIZE is 0
            for (String tr : tableRows) {
                System.out.println(tr);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

答案 2 :(得分:1)

这是一种方式(似乎应该有一种方法可以使用LIMIT,但我现在无法提出一种方法。)

我用

生成了一个示例图
FOREACH (a IN [[1,2,10],[1,3,8],[1,5,7],[2,21,34],[2,17,20],[2,35,15],[3,5,49],[3,333,30],[3,65,5],[1,4,1],[3,6,100]]| MERGE (p:Product { id:a[0]})
     MERGE (q:Product { id:a[1]})
     CREATE p-[b:BOUGHT_TOGETHER { size:a[2]}]->q
)

这是您所需输出表中的数据,另外还有两项:[1,4,1][3,5,100]。对于某些节点有三个以上的关系有助于我们测试查询是否得到正确的三个 - 1的结果不应包含[1,4,1],而3的结果现在应该包含{{1}而不是[3,6,100]

如果这是您的数据的准确样本,那么此查询应该执行您想要的操作:

[3,5,5]

我们的想法是按MATCH (p:Product)-[b:BOUGHT_TOGETHER]-(q:Product) WITH p.id AS pid, q.id AS qid, b.size AS bsize ORDER BY bsize DESC WITH pid, collect([qid, bsize])[..3] AS qb UNWIND qb AS uqb RETURN pid, uqb[0] AS qid, uqb[1] AS bsize ORDER BY pid, bsize DESC 订购所有结果项,然后按b.size收集它们,然后丢弃除每个集合中前三项之外的所有项目,然后展开并返回。结果看起来与输出表不完全相同,因为它也包含了另一个方向的关系(p以及[5,1,7]),但我认为这就是你想要的。

如果这样做,您可能希望看看是否可以推迟读取属性,直到修剪集合以保存一些数据库命中为止。