【问题标题】:Order then paginate with neo4j-will_paginate订购然后用 neo4j-will_paginate 分页
【发布时间】:2014-12-27 19:07:14
【问题描述】:

我正在尝试在我的 rails 应用程序上使用 neo4j-will_paginate gem 实现分页,但在排序记录然后对其进行分页时遇到问题。

如果我尝试:

@things = Thing.all.order(title: :desc) 

@things = Thing.all.paginate(:page => params[:page], :per_page => 20)

这些单独工作正常,但如果我尝试

@things = Thing.all.order(title: :desc).paginate(:page => params[:page], :per_page => 20)

它会导致“未知标识符 `n`”。错误

从 rails 服务器,生成的 Cypher 查询是:

CYPHER 13ms MATCH (n:`Thing`) RETURN count(n) AS count ORDER BY n.title DESC
Completed 500 Internal Server Error in 14ms
Neo4j::Session::CypherError (Unknown identifier `n`.):

我也试过

@things = Thing.all.paginate(:page => params[:page], :per_page => 2, :order => 'title DESC')

没有报错,但是结果没有排序。

如果能得到任何帮助,我将不胜感激!提前致谢!

【问题讨论】:

    标签: ruby-on-rails neo4j will-paginate


    【解决方案1】:

    我就是那个人,嗯……这很尴尬……责备这个问题。 neo4j-will_paginate gem 很快就适应了 Neo4jrb 3.0,因此,自从它发布以来,我一直在根据需要对其进行修补。

    无论如何,失败的原因有两个,而且都不是你的错。我刚刚修补了 Neo4j 和 neo4j-will_paginate gem 来解决这个问题。正如您在上次尝试中演示的那样,我添加了一个 order 选项,但您需要使用带标识符的符号、哈希或字符串。其中之一:

    @things = Thing.all.paginate(:page => params[:page], :per_page => 2, :order => :title)
    @things = Thing.all.paginate(:page => params[:page], :per_page => 2, :order => { title: :desc })
    @things = Thing.as(:t).paginate(:page => params[:page], :per_page => 2, :order => 't.title DESC')
    

    在我们为 neo4j 发布新版本之前,我无法发布 neo4j-will_paginate 的新版本,因此在此期间,请将您的 gemfile 指向每个 repo 的 master 分支或引用注明的提交。

    gem 'neo4j', github: 'neo4jrb/neo4j', branch: 'master', 
    gem 'neo4j-will_paginate', github: 'neo4jrb/neo4j-will_paginate', branch: 'master'
    
    #or
    
    gem 'neo4j', github: 'neo4jrb/neo4j', ref: 'b4ee152becb827d87a7659d1beebfb043d0560f6'
    gem 'neo4j-will_paginate', github: 'neo4jrb/neo4j-will_paginate', ref: 'b85b622087f3929c37231570f4d24021dcff4ee0'
    

    我们为 Neo4j 保留了一个完全通过的 master 分支。

    在直接在 gem 中修复它之前,我找出了问题的原因和一个糟糕的解决方法并输入了它。我将把它包括在这里,因为它揭示了一些关于为什么会发生这种情况的信息,以及当它们弹出时如何解决 Cypher DSL 的限制。最终,您对paginate 中的order 选项的建议让我了解了如何正确处理它。


    不必要的解决方法:

    Thing.as(:t).where('true = true WITH t ORDER BY t.name desc').paginate(:page => params[:page], :per_page => 2)
    

    在 Cypher 中,这会产生两个查询:

    MATCH (t:`Thing`) WHERE true = true WITH t ORDER BY t.name desc RETURN count(DISTINCT t) AS t
    MATCH (t:`Thing`) WHERE true = true WITH t ORDER BY t.name desc RETURN t SKIP 0 LIMIT 10
    

    请务必注意我们在开头设置了 as 的标识符。只要在where方法中使用相同的东西,你就可以设置任何你想要的东西。

    所有必要的原因是will_paginate 如何计算要显示的总页数。当您调用 paginate 时,您的查询调用了 count,正如您在第一个 Cypher 语句中看到的那样。现在 count 错误已得到修复(EDIT 这包含在介绍部分中,我在其中提到修复导致您的特定错误但不是整个问题的错误),看起来像这个:

    MATCH (result:`Thing`) RETURN count(result) AS result ORDER BY result.name, result.desc
    # results in error:
    # Neo4j::Session::CypherError: Type mismatch: expected Map, Node or Relationship but was Integer (line 1, column 66)
    

    查询和顺序清楚地表明了问题所在:您不能对整数进行排序。 WITH 救援! WITH 本质上将我们的单个查询分成两个单独的查询。通常必须作为RETURN 的一部分调用的子句可以在那里调用。我们在那里而不是在最后执行我们的命令,然后我们让其余部分像往常一样播放。

    这是个好主意,但这里的问题是QueryProxyNeo4j::Core::Query 类的抽象,没有with 方法。我们用where('true = true... 废话解决了这个问题。我们本质上是对服务器使用 Cypher Injection 攻击。哎哟。

    我想我可以通过修补 gem 来使用 with...


    此时,我确切地意识到它是如何工作的,停止打字,并修补了 gem。结束。我在https://github.com/neo4jrb/neo4j/issues/540 创建了一个问题,如果您有任何问题,请随时在此发表评论。

    【讨论】:

    • 非常感谢您修补 gem!新的订单选项完美运行:) 我从 current_user 和 devise-neo4j 的其他方法收到错误,特别是 wrong number of arguments (1 for 0)。如果需要,我会尝试更深入地挖掘并在 github 页面上发布。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 2020-08-31
    相关资源
    最近更新 更多