Neo4j Cypher:限制所选节点的返回链接数

Neo4j Cypher:限制所选节点的返回链接数,neo4j,cypher,Neo4j,Cypher,我在一个显然很简单的问题上失败了 算法: 按某个值对节点排序(desc): 对于每个节点,返回其直接邻居(按第二个值排序): 挑战在于返回前100个n节点,每个节点仅返回10个关系r(如果可能,在一行中) 编辑: 对不起,我说的太不具体了,以至于人们误解了我 详细地说,下面的查询为我提供了排序的顶部节点: MATCH (n) WHERE HAS(n.II_VAL) WITH n, n.`II_VAL` AS ShInflInd ORDER BY ShInflInd DESC RETURN n

我在一个显然很简单的问题上失败了

算法:

  • 按某个值对节点排序(desc):

  • 对于每个节点,返回其直接邻居(按第二个值排序):

  • 挑战在于返回前100个n节点,每个节点仅返回10个关系r(如果可能,在一行中)

    编辑:

    对不起,我说的太不具体了,以至于人们误解了我

    详细地说,下面的查询为我提供了排序的顶部节点:

    MATCH (n) WHERE HAS(n.II_VAL)
    WITH n, n.`II_VAL` AS ShInflInd ORDER BY ShInflInd DESC
    RETURN n.NAME LIMIT 100;
    
    +--------------------------------------+
    | n.NAME                               |
    +--------------------------------------+
    | "PUBLIC"                             |
    | "BARCLAYS PLC"                       |
    
    现在,我可以将子查询添加到此中,其中添加了链接:

    MATCH (n) WHERE HAS(n.II_VAL)
    WITH n, n.`II_VAL` AS ShInflInd ORDER BY ShInflInd DESC LIMIT 100
    MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
    WITH r, n, m, m.VALUE AS SubsOpRev
    RETURN n.NAME, r.WEIGHT_MERGED, m.NAME, SubsOpRev LIMIT 10;
    
    +----------------------------------------------------------------------------------------+
    | n.NAME   | r.WEIGHT_MERGED    | m.NAME                                     | SubsOpRev |
    +----------------------------------------------------------------------------------------+
    | "PUBLIC" | 0.66               | "VBS MUTUAL BANK"                          | 2630      |
    | "PUBLIC" | 0.2923             | "STRATCORP LIMITED"                        | 10842     |
    
    现在我想要的是,在返回“PUBLIC”的10个链接(可能按r.WEIGHT_MERGED或subsprov排序)之后,查询返回第二个节点(“巴克莱PLC”)及其10个链接,等等

    我试过:

    MATCH (n) WHERE HAS(n.II_VAL)
    WITH n, n.`II_VAL` AS ShInflInd ORDER BY ShInflInd DESC
    MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
    WITH r, n, m, m.VALUE AS SubsOpRev
    RETURN collect([n.NAME, r.WEIGHT_MERGED, m.NAME, SubsOpRev])[0..10];
    
    导致:

    +------------------------------------------------------------------------------------------------------------------------------------------+
    | collect([n.NAME, r.WEIGHT_MERGED, m.NAME, SubsOpRev])[0..3]                                                                              |
    +------------------------------------------------------------------------------------------------------------------------------------------+
    | [["PUBLIC",0.66,"VBS MUTUAL BANK",2630],["PUBLIC",0.2923,"STRATCORP LIMITED",10842], ...
    
    这意味着我仍然坚持“公开”

    稍微修改查询会使情况变得更糟,因为它返回完全不同的数据:

    MATCH (n) WHERE HAS(n.II_VAL)
    WITH n, n.`II_VAL` AS ShInflInd ORDER BY ShInflInd DESC
    MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
    WITH r, n, m, m.VALUE AS SubsOpRev
    RETURN n.NAME, collect([r.WEIGHT_MERGED, m.NAME, SubsOpRev])[0..10] LIMIT 3;
    
    +------------------------------------------------------------------------------+
    | n.NAME                | collect([r.WEIGHT_MERGED, m.NAME, SubsOpRev])[0..10] |
    +------------------------------------------------------------------------------+
    | "RS-INVEST AS"        | [[0.5,"VERUCO EIENDOM AS",100]]                      |
    | "DBM"                 | [[0.1435,"CHELYABINSKOBLGAZ",6752]]                  |
    
    理想情况下,查询应该产生如下结果

    | [["PUBLIC",0.66,"VBS MUTUAL BANK",2630],["PUBLIC",0.2923,"STRATCORP LIMITED",10842], ... |
    | [["BARCLAYS PLC",x,"XYZ",y], ... |
    

    你能描述一下问题是什么吗

    最大的问题似乎是您没有使用
    返回完成查询<代码>与
    用于中间传递数据。此外,实际上不需要提取值来对其进行排序。您可以这样做:

    MATCH (n)
    WHERE has(n.II_VAL)
    RETURN n ORDER BY n.II_VAL DESC LIMIT 100
    
    关于第二个问题:

    MATCH (n)-[r]->(m)
    RETURN n, m ORDER BY m.VALUE DESC LIMIT 100
    

    编辑:对不起,忘记了
    限制

    要根据第一次查询获得前100个节点,必须在订单后添加
    返回
    子句和
    限制
    子句:

    MATCH (n) 
    WHERE has(n.II_VAL) 
    RETURN n, n.II_VAL as ShInflInd 
    order by ShInflInd desc 
    LIMIT 100
    

    对于第二个,您必须执行两个查询,并在客户端实现Foreach逻辑。因为您不能将第一个限制为100,然后在同一查询中为每个节点获取10个相关节点。

    您可以将节点数限制为100:

    MATCH (n)
    WHERE has(n.II_VAL)
    WITH n, n.II_VAL AS ShInflInd
    ORDER BY ShInflInd DESC 
    LIMIT 100
    
    您可以收集所有
    subprev
    ,然后
    RETURN
    收集的片段。沿着这条线(我假设
    subprev
    就是您想要的):


    这将为您提供每行一个节点
    n
    ,以及所有收集的
    subsprev

    列表的一部分。我想您的意思是希望在一个查询中返回两组结果。要做到这一点,我认为最好的办法是在
    中用
    收集
    ,这只会给您一行,然后
    返回该值以及其他数据的
    收集
    。比如:

    MATCH (n) WHERE HAS(n.II_VAL)
    WITH collect([n, n.`II_VAL`])[0..100] AS set1 ORDER BY n.`II_VAL` DESC
    MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
    RETURN set1, collect([n.NAME, r.WEIGHT_MERGED, m.NAME])[1..10] ORDER BY r.WEIGHT_MERGED
    
    我加入了
    orderbyr.WEIGHT\u MERGED
    ,作为如何再次按值排序的示例

    如果您希望数据更结构化,还可以收集对象贴图,而不是像这样的数组:

    MATCH (n) WHERE HAS(n.II_VAL)
    WITH collect({n: n, II_VAL: n.`II_VAL`})[0..100] AS set1 ORDER BY n.`II_VAL` DESC
    MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
    RETURN set1, collect({n_name: n.NAME, weight_merged: r.WEIGHT_MERGED, m_name: m.NAME})[1..10] ORDER BY r.WEIGHT_MERGED
    
    MATCH (n) WHERE HAS(n.II_VAL)
    WITH n ORDER BY n.II_VAL DESC LIMIT 100
    MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
    WITH n, r, m ORDER BY m.VALUE DESC
    RETURN n.NAME, COLLECT([r.WEIGHT_MERGED, m.NAME, m.VALUE])[0..10];
    

    您只需要限制,然后继续查询。为了提供一个可复制的示例,让我们切换到Neo4j附带的电影数据集。假设你想抓取数据库中最老的3部电影,然后抓取其中每部电影中最老的2名演员

    MATCH (m:Movie)
    WITH m ORDER BY m.released LIMIT 3
    MATCH (p:Person)-[:ACTED_IN]->(m)
    WITH m, p ORDER BY p.born
    WITH m, COLLECT(p.name)[0..2] AS oldest
    RETURN m.title, oldest;
    
    这将产生:

       | m.title                         | oldest                              
    ---+---------------------------------+--------------------------------------
     1 | Something's Gotta Give          | ['Jack Nicholson', 'Diane Keaton']
     2 | Top Gun                         | ['Tom Skerritt', 'Kelly McGillis']
     3 | One Flew Over the Cuckoo's Nest | ['Jack Nicholson', 'Danny DeVito']
    
    所以你会想要这样的东西:

    MATCH (n) WHERE HAS(n.II_VAL)
    WITH collect({n: n, II_VAL: n.`II_VAL`})[0..100] AS set1 ORDER BY n.`II_VAL` DESC
    MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
    RETURN set1, collect({n_name: n.NAME, weight_merged: r.WEIGHT_MERGED, m_name: m.NAME})[1..10] ORDER BY r.WEIGHT_MERGED
    
    MATCH (n) WHERE HAS(n.II_VAL)
    WITH n ORDER BY n.II_VAL DESC LIMIT 100
    MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
    WITH n, r, m ORDER BY m.VALUE DESC
    RETURN n.NAME, COLLECT([r.WEIGHT_MERGED, m.NAME, m.VALUE])[0..10];
    

    查询片段仅用于说明。请查看对我原始帖子的编辑。我没有使用循环。请查看对我的原始帖子的编辑。我需要合并这两个查询。请查看对我原始帖子的编辑。你可以将它们合并。关于您的编辑:您必须先
    排序
    ,然后
    收集()
    仅返回要返回的关系或值。如果您希望再次拥有相同的节点顺序,您可能希望在
    返回中再次排序。是的,但我需要向从第一次排序搜索中获得的每个节点添加一个子查询(检索10个链接)。我不知道如何以一种非常简单的方式组合查询…好的,关闭:)但是,查询不知道第二行中的“n”(“n未定义”)(按n.
    II_VAL
    排序)。如果我将它添加到“WITH”(WITH n,collect({n…)我将原来的排序按n.
    II_VAL
    松开。但是它返回的内容的结构与我正在寻找的内容类似…将其从
    WITH
    子句中删除,您正在失去绑定
    n
    ;此时,您只需在第3行的所有节点上进行匹配。这正是我需要的,谢谢。通过以下小的添加,我再次得到按n.II_VAL排序的最终列表:“…n,n.II_VAL为II,r,m按m.VALUE DESC排序返回n.NAME,II,COLLECT([r.WEIGHT_MERGED,m.NAME,m.VALUE])[0..2]按II DESC排序
    MATCH (n) WHERE HAS(n.II_VAL)
    WITH n ORDER BY n.II_VAL DESC LIMIT 100
    MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
    WITH n, r, m ORDER BY m.VALUE DESC
    RETURN n.NAME, COLLECT([r.WEIGHT_MERGED, m.NAME, m.VALUE])[0..10];