Rails Neo4j查询返回CypherRelationship而不是关系值

时间:2016-05-14 14:41:02

标签: ruby-on-rails neo4j.rb

我正在研究一个使用Neo4j作为数据库跟踪地址之间事务的Rails应用程序。当我尝试运行此查询时:

Neo4j::Session.query("MATCH (sender:Address {address: 'abc123'})-[transaction:SENT_TO]->(receiver:Address) RETURN sender, transaction, receiver").to_a

我按预期返回一个数组,但transaction项作为CypherRelationship指针而不是其属性的结构返回,就像它对发送方和接收方地址一样:

=> [#<struct sender=#<Address uuid: nil, address: "abc123", user_tags: nil>, transaction=CypherRelationship 30, receiver=#<Address uuid: nil, address: "xyz321", user_tags: nil>>]

如果我尝试通过执行transaction.props['amount']之类的操作获取其中一个事务属性,则会导致新的Cypher查询运行。由于我想要在每个事务上返回多个属性,以及将返回的大量事务,我希望初始查询只是将关系的属性作为数组中的结构返回。

当我在Neo4j中直接运行查询时,这是我想要的,所以我怀疑它是neo4j-core gem的一个问题(或者我对它的使用)......任何想法?

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

Neo4j和Neo4j核心宝石提供节点和关系的对象表示,但哪个对象最终取决于应用中定义的类。返回节点或关系时,Neo4j gem会尝试根据标签或rel类型查找对其负责的模型。找到一个时,它返回该类的实例;当找不到一个时,它返回Neo4j-core提供的一个基本类的实例:CypherNodeCypherRelationship

在你的情况下,你没有得到属性的结构,你得到类型为Address的节点的结构,因为你定义了那个模型,而CypherRelationship,所以你没有有一个为这种关系定义的模型。模型的实例具有获取和设置属性的便捷方法,但CypherNodeCypherRelationship的实例却没有,因此调用props并且您将可以访问关系的属性。

您可能需要查看CypherRelationship代码。 https://github.com/neo4jrb/neo4j-core/blob/master/lib/neo4j-server/cypher_relationship.rb是它的主要部分,但它继承自https://github.com/neo4jrb/neo4j-core/blob/master/lib/neo4j/relationship.rb,它主要是一个抽象类,但它也提供了一些其他方法。它有一个非常基本的公共界面,主要是处理关系的便捷方法。 CypherNode非常相似:https://github.com/neo4jrb/neo4j-core/blob/master/lib/neo4j-server/cypher_node.rb

一般来说,我的建议是使用Neo4j::ActiveRel为您计划在Ruby中作为对象使用的任何关系定义模型。您可以在http://neo4jrb.readthedocs.io/en/v7.0.2/ActiveRel.html找到相关文档。

另外两个注释:

  • 如果您的查询被指示返回属性而不是完整对象,您将收到Structs而不是CypherNode / CypherRelationship的实例或您的模型类。

  • 如果您使用Cypher DSL而不是传入查询,则可以使用pluck方法并接收对象阵列而不是结构,如果您愿意的话。 return(symbols).to_a也可以。

Neo4j::Session.current.query
      .match("(sender:Address {address: {addr} })-[transaction:SENT_TO]->(receiver:Address)")
      .params(addr: 'abc123')
      .pluck(:sender, :transaction, :receiver)