Skip to content
Chris Grigg edited this page Sep 1, 2014 · 12 revisions

There are a few ways to find and return nodes.

find returns one ruby object or nil if none was found.

# Example, find by id (neo_id or defined by id_property)
Blog.find(4242)

find_by and find_by! behave as they do in ActiveRecord, returning the first object matching the criteria or either nil or an error in the case of find_by!

Blog.find_by(title: 'Neo4j.rb is awesome')

Basic querying

All of the following result in enumerable results:

# Find all blog models
Blog.all

# Limit results
Blog.where(title: 'neo4j')

# Order
Person.where(age: 30).order(age: :desc).limit(5)

You should use params method whenever dealing with user-submitted data in a where clause to prevent Cypher injection.

Student.where(age: '{age}', name: '{name}', home_town: '{home_town}').params(age: params[:age], name: params[:name], home_town: params[:home_town]).first
Student.query_as(:s).where("s.age < {age} AND s.name = {name} AND s.home_town = {home_town}").params(age: params[:age], name: params[:name], home_town: params[:home_town]).pluck(:s)

When using quotes within a where clause, you can use full cypher syntax. See http://docs.neo4j.org/chunked/stable/query-syntax.html.

Detailed querying

The ActiveNode.query_as and ActiveNode#query_as methods return Query objects which allow you to chain together query clauses and then determine how you'd like the results to be returned.

# Find all comments for any blog which have the world "pottery"
result = Blog.query_as(:blog).match("blog<-[:COMMENTS_ON]-(comment:Comment)").where(comment: {body: /pottery/}).pluck(:blog, :comment)
result.first.blog     # First blog
result.first.comment  # Comment

# Find all comment authors whose age is greater than 30
blog.query_as(:blog).match("blog<-[:COMMENTS_ON]-(:Comment)<-[:AUTHORED]-(author:Person)").where("author.age > 30").pluck(:author)

# You can even get start with basic query methods and then transfer to detailed querying
blog.where(title: 'neo4j').query_as(:blog).match("blog<--(comment:Comment)").where("comment.created_at >= '2014-07-09'").pluck(:comment)

For more information on Query objects, see the (Neo4j::Core::Query documentation)[https://github.com/neo4jrb/neo4j-core/wiki/Queries#examples].

Returning objects

An explicit return method does not need to be called if you want to return the last matching node in a query chain.

User.where(age: 30).lessons.where(level: 101)

Calling each on this would iterate through objects of class Lesson, no need to tell it what to return.

If you want something other than the last object or you want distinct results, use pluck or return. return is a method from neo4j-core and is usable after calling query or query_as, so see neo4j-core docs for examples. This will focus on pluck.

pluck is used to return matched nodes or relationships in queries. There are two reasons to use it:

You want to return a node or group of nodes from a query other than just the nodes at the end of the chain.

#pluck not needed, returns the lessons that are level 101 of all users who are age 30
User.where(age: 30).lessons.where(level: 101)
#call each, first, include?, etc,...

#return the users who are age 30 and have lessons with level 101
User.as(:u).where(age: 30).lessons.where(level: 101).pluck(:u)

#return both the users and the lessons
User.as(:u).where(age: 30).lessons(:l).where(level: 101).pluck(:u, :l)

You want distinct results.

#assign your node an identifier, call pluck with a string
User.where(age: 30).lessons(:l).where(level: 101).pluck('DISTINCT l')

In both cases, pluck expects a node identifier.

You can also pluck relationships based on their identifiers.

# return the relationship between users, age 30, who have lessons with level 101
User.where(age: 30).lessons(:l, :rel).where(level: 101).pluck(:rel)

Note that plucking the relationship may not be necessary if you plan on iterating through the results with each.

User.where(age: 30).lessons(:l, :rel).where(level: 101).pluck(:rel).each do |rel|
# is equivalent to...
User.where(age: 30).lessons.where(level: 101).each_rel do |rel|
# or with both nodes and relationships
User.where(age: 30).lessons.where(level: 101).each_with_rel do |lesson, rel|

Orm_Adapter

You can also use the orm_adapter API, by calling #to_adapter on your class. See the API, https://github.com/ianwhite/orm_adapter

Cypher

Same as in neo4j-core, see Neo4j::Session.query

Clone this wiki locally