Запрос Rails Neo4j возвращает CypherRelationship вместо значений отношения

Я работаю над приложением Rails, которое отслеживает транзакции между адресами, используя Neo4j в качестве базы данных. Когда я пытаюсь запустить этот запрос:

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 (или моим его использованием) ... есть идеи?

Спасибо за вашу помощь!


person btw09    schedule 14.05.2016    source источник


Ответы (1)


Драгоценные камни Neo4j и Neo4j-core обеспечивают объектное представление узлов и отношений, но какой объект вы получите, полностью зависит от классов, определенных в вашем приложении. Когда возвращается узел или отношение, гем Neo4j пытается найти ответственную за него модель на основе меток или типа отношения. Когда он найден, он возвращает экземпляр этого класса; когда он не найден, он возвращает экземпляр одного из базовых классов, предоставляемых Neo4j-core: CypherNode или CypherRelationship.

В вашем случае вы не получаете структуры свойств, вы получаете структуры узлов типа Address, поскольку у вас определена эта модель, и CypherRelationship, поэтому у вас нет модели, определенной для этого типа отношений. Экземпляры ваших моделей имеют удобные методы для получения и установки свойств, а экземпляры CypherNode и CypherRelationship — нет, поэтому вызовите 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.

Два других замечания:

  • Вы получите структуры вместо экземпляров 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)
person subvertallchris    schedule 14.05.2016