class Neo4j::Core::Query

Allows for generation of cypher queries via ruby method calls (inspired by ActiveRecord / arel syntax)

Can be used to express cypher queries in ruby nicely, or to more easily generate queries programatically.

Also, queries can be passed around an application to progressively build a query across different concerns

See also the following link for full cypher language documentation: docs.neo4j.org/chunked/milestone/cypher-query-lang.html

Constants

BREAK_METHODS
CLAUSES
CLAUSIFY_CLAUSE
DEFINED_CLAUSES
EMPTY

Returns a CYPHER query string from the object query representation @example

Query.new.match(p: :Person).where(p: {age: 30})  # => "MATCH (p:Person) WHERE p.age = 30

@return [String] Resulting cypher query string

METHODS

@method detach_delete *args DETACH DELETE clause @return [Query]

NEWLINE

Attributes

pretty_cypher[RW]
_params[RW]
clauses[RW]
options[RW]
session[RW]

Public Class Methods

new(options = {}) click to toggle source
   # File lib/neo4j/core/query.rb
70 def initialize(options = {})
71   @session = options[:session]
72 
73   @options = options
74   @clauses = []
75   @_params = {}
76   @params = Parameters.new
77 end

Public Instance Methods

&(other) click to toggle source
    # File lib/neo4j/core/query.rb
393 def &(other)
394   self.class.new(session: @session).tap do |new_query|
395     new_query.options = options.merge(other.options)
396     new_query.clauses = clauses + other.clauses
397   end.params(other._params)
398 end
break() click to toggle source

Allows what's been built of the query so far to be frozen and the rest built anew. Can be called multiple times in a string of method calls @example

# Creates a query representing the cypher: MATCH (q:Person), r:Car MATCH (p: Person)-->q
Query.new.match(q: Person).match('r:Car').break.match('(p: Person)-->q')
    # File lib/neo4j/core/query.rb
213 def break
214   build_deeper_query(nil)
215 end
clause?(method) click to toggle source
    # File lib/neo4j/core/query.rb
409 def clause?(method)
410   clause_class = DEFINED_CLAUSES[method] || CLAUSIFY_CLAUSE.call(method)
411   clauses.any? { |clause| clause.is_a?(clause_class) }
412 end
context() click to toggle source
    # File lib/neo4j/core/query.rb
362 def context
363   @options[:context]
364 end
copy() click to toggle source
    # File lib/neo4j/core/query.rb
400 def copy
401   dup.tap do |query|
402     to_cypher
403     query.instance_variable_set('@params'.freeze, @params.copy)
404     query.instance_variable_set('@partitioned_clauses'.freeze, nil)
405     query.instance_variable_set('@response'.freeze, nil)
406   end
407 end
count(var = nil) click to toggle source
    # File lib/neo4j/core/query.rb
271 def count(var = nil)
272   v = var.nil? ? '*' : var
273   pluck("count(#{v})").first
274 end
cypher(options = {})
Alias for: to_cypher
each() { |object| ... } click to toggle source
    # File lib/neo4j/core/query.rb
276 def each
277   response = self.response
278   if defined?(Neo4j::Server::CypherResponse) && response.is_a?(Neo4j::Server::CypherResponse)
279     response.unwrapped! if unwrapped?
280     response.to_node_enumeration
281   elsif defined?(Neo4j::Core::CypherSession::Result) && response.is_a?(Neo4j::Core::CypherSession::Result)
282     response.to_a
283   else
284     Neo4j::Embedded::ResultWrapper.new(response, to_cypher, unwrapped?)
285   end.each { |object| yield object }
286 end
exec() click to toggle source

Executes a query without returning the result @return [Boolean] true if successful @raise [Neo4j::Server::CypherResponse::ResponseError] Raises errors from neo4j server

    # File lib/neo4j/core/query.rb
297 def exec
298   response
299 
300   true
301 end
inspect() click to toggle source
   # File lib/neo4j/core/query.rb
79 def inspect
80   "#<Query CYPHER: #{ANSI::YELLOW}#{to_cypher.inspect}#{ANSI::CLEAR}>"
81 end
match_nodes(hash, optional_match = false) click to toggle source
    # File lib/neo4j/core/query.rb
256 def match_nodes(hash, optional_match = false)
257   hash.inject(self) do |query, (variable, node_object)|
258     neo_id = (node_object.respond_to?(:neo_id) ? node_object.neo_id : node_object)
259 
260     match_method = optional_match ? :optional_match : :match
261     query.send(match_method, variable).where(variable => {neo_id: neo_id})
262   end
263 end
optional_match_nodes(hash) click to toggle source
    # File lib/neo4j/core/query.rb
265 def optional_match_nodes(hash)
266   match_nodes(hash, true)
267 end
parameters() click to toggle source
    # File lib/neo4j/core/query.rb
366 def parameters
367   to_cypher
368   merge_params
369 end
params(args) click to toggle source

Allows for the specification of values for params specified in query @example

# Creates a query representing the cypher: MATCH (q: Person {id: {id}})
# Calls to params don't affect the cypher query generated, but the params will be
# Passed down when the query is made
Query.new.match('(q: Person {id: {id}})').params(id: 12)
    # File lib/neo4j/core/query.rb
224 def params(args)
225   copy.tap { |new_query| new_query.instance_variable_get('@params'.freeze).add_params(args) }
226 end
partitioned_clauses() click to toggle source
    # File lib/neo4j/core/query.rb
371 def partitioned_clauses
372   @partitioned_clauses ||= PartitionedClauses.new(@clauses)
373 end
pluck(*columns) click to toggle source

Return the specified columns as an array. If one column is specified, a one-dimensional array is returned with the values of that column If two columns are specified, a n-dimensional array is returned with the values of those columns

@example

Query.new.match(n: :Person).return(p: :name}.pluck(p: :name) # => Array of names

@example

Query.new.match(n: :Person).return(p: :name}.pluck('p, DISTINCT p.name') # => Array of [node, name] pairs
    # File lib/neo4j/core/query.rb
312 def pluck(*columns)
313   fail ArgumentError, 'No columns specified for Query#pluck' if columns.size.zero?
314 
315   query = return_query(columns)
316   columns = query.response.columns
317 
318   if columns.size == 1
319     column = columns[0]
320     query.map { |row| row[column] }
321   else
322     query.map { |row| columns.map { |column| row[column] } }
323   end
324 end
pretty_cypher() click to toggle source
    # File lib/neo4j/core/query.rb
358 def pretty_cypher
359   to_cypher(pretty: true)
360 end
print_cypher() click to toggle source
raise_if_cypher_error!(response) click to toggle source
    # File lib/neo4j/core/query.rb
252 def raise_if_cypher_error!(response)
253   response.raise_cypher_error if response.respond_to?(:error?) && response.error?
254 end
reorder(*args) click to toggle source

Clears out previous order clauses and allows only for those specified by args

    # File lib/neo4j/core/query.rb
188 def reorder(*args)
189   query = copy
190 
191   query.remove_clause_class(OrderClause)
192   query.order(*args)
193 end
response() click to toggle source
    # File lib/neo4j/core/query.rb
241 def response
242   return @response if @response
243 
244   @response = if session_is_new_api?
245                 @session.query(self, transaction: Transaction.current_for(@session), wrap_level: (:core_entity if unwrapped?))
246               else
247                 @session._query(to_cypher, merge_params,
248                                 context: @options[:context], pretty_cypher: (pretty_cypher if self.class.pretty_cypher)).tap(&method(:raise_if_cypher_error!))
249               end
250 end
return_query(columns) click to toggle source
    # File lib/neo4j/core/query.rb
326 def return_query(columns)
327   query = copy
328   query.remove_clause_class(ReturnClause)
329 
330   query.return(*columns)
331 end
session_is_new_api?() click to toggle source
    # File lib/neo4j/core/query.rb
237 def session_is_new_api?
238   defined?(::Neo4j::Core::CypherSession) && @session.is_a?(::Neo4j::Core::CypherSession)
239 end
set_props(*args) click to toggle source

Works the same as the set method, but when given a nested array it will set properties rather than setting entire objects @example

# Creates a query representing the cypher: MATCH (n:Person) SET n.age = 19
Query.new.match(n: :Person).set_props(n: {age: 19})
    # File lib/neo4j/core/query.rb
205 def set_props(*args) # rubocop:disable Naming/AccessorMethodName
206   build_deeper_query(SetClause, args, set_props: true)
207 end
to_cypher(options = {}) click to toggle source
    # File lib/neo4j/core/query.rb
340 def to_cypher(options = {})
341   join_string = options[:pretty] ? NEWLINE : EMPTY
342 
343   cypher_string = partitioned_clauses.map do |clauses|
344     clauses_by_class = clauses.group_by(&:class)
345 
346     cypher_parts = CLAUSES.map do |clause_class|
347       clause_class.to_cypher(clauses, options[:pretty]) if clauses = clauses_by_class[clause_class]
348     end.compact
349 
350     cypher_parts.join(join_string).tap(&:strip!)
351   end.join(join_string)
352 
353   cypher_string = "CYPHER #{@options[:parser]} #{cypher_string}" if @options[:parser]
354   cypher_string.tap(&:strip!)
355 end
Also aliased as: cypher
union_cypher(other, options = {}) click to toggle source

Returns a CYPHER query specifying the union of the callee object's query and the argument's query

@example

# Generates cypher: MATCH (n:Person) UNION MATCH (o:Person) WHERE o.age = 10
q = Neo4j::Core::Query.new.match(o: :Person).where(o: {age: 10})
result = Neo4j::Core::Query.new.match(n: :Person).union_cypher(q)

@param other [Query] Second half of UNION @param options [Hash] Specify {all: true} to use UNION ALL @return [String] Resulting UNION cypher query string

    # File lib/neo4j/core/query.rb
389 def union_cypher(other, options = {})
390   "#{to_cypher} UNION#{options[:all] ? ' ALL' : ''} #{other.to_cypher}"
391 end
unwrapped() click to toggle source
    # File lib/neo4j/core/query.rb
228 def unwrapped
229   @_unwrapped_obj = true
230   self
231 end
unwrapped?() click to toggle source
    # File lib/neo4j/core/query.rb
233 def unwrapped?
234   !!@_unwrapped_obj
235 end
where_not(*args) click to toggle source

Works the same as the where method, but the clause is surrounded by a Cypher NOT() function

    # File lib/neo4j/core/query.rb
197 def where_not(*args)
198   build_deeper_query(WhereClause, args, not: true)
199 end

Protected Instance Methods

add_clauses(clauses) click to toggle source
    # File lib/neo4j/core/query.rb
418 def add_clauses(clauses)
419   @clauses += clauses
420 end
remove_clause_class(clause_class) click to toggle source
    # File lib/neo4j/core/query.rb
422 def remove_clause_class(clause_class)
423   @clauses = @clauses.reject { |clause| clause.is_a?(clause_class) }
424 end

Private Instance Methods

build_deeper_query(clause_class, args = {}, options = {}) click to toggle source
    # File lib/neo4j/core/query.rb
428 def build_deeper_query(clause_class, args = {}, options = {})
429   copy.tap do |new_query|
430     new_query.add_clauses [nil] if [nil, WithClause].include?(clause_class)
431     new_query.add_clauses clause_class.from_args(args, new_query.instance_variable_get('@params'.freeze), options) if clause_class
432   end
433 end
merge_params() click to toggle source

SHOULD BE DEPRECATED

    # File lib/neo4j/core/query.rb
498 def merge_params
499   @merge_params_base ||= @clauses.compact.inject({}) { |params, clause| params.merge!(clause.params) }
500   @params.to_hash.merge(@merge_params_base)
501 end