QueryProxyMethods

Constants

  • FIRST
  • LAST

Methods

#all_rels_to

Returns all relationships across a QueryProxy chain between a given node or array of nodes and the preceeding link.

def rels_to(node)
  self.match_to(node).pluck(rel_var)
end
#as_models

Takes an Array of ActiveNode models and applies the appropriate WHERE clause So for a Teacher model inheriting from a Person model and an Article model if you called .as_models([Teacher, Article]) The where clause would look something like:

WHERE (node_var:Teacher:Person OR node_var:Article)
def as_models(models)
  where_clause = models.map do |model|
    "`#{identity}`:" + model.mapped_label_names.map do |mapped_label_name|
      "`#{mapped_label_name}`"
    end.join(':')
  end.join(' OR ')

  where("(#{where_clause})")
end

#blank?

def empty?(target = nil)
  query_with_target(target) { |var| !self.exists?(nil, var) }
end

#count

def count(distinct = nil, target = nil)
  fail(Neo4j::InvalidParameterError, ':count accepts `distinct` or nil as a parameter') unless distinct.nil? || distinct == :distinct
  query_with_target(target) do |var|
    q = distinct.nil? ? var : "DISTINCT #{var}"
    limited_query = self.query.clause?(:limit) ? self.query.break.with(var) : self.query.reorder
    limited_query.pluck("count(#{q}) AS #{var}").first
  end
end

#empty?

def empty?(target = nil)
  query_with_target(target) { |var| !self.exists?(nil, var) }
end

#exists?

def exists?(node_condition = nil, target = nil)
  unless node_condition.is_a?(Integer) || node_condition.is_a?(Hash) || node_condition.nil?
    fail(Neo4j::InvalidParameterError, ':exists? only accepts neo_ids')
  end
  query_with_target(target) do |var|
    start_q = exists_query_start(node_condition, var)
    start_q.query.reorder.return("COUNT(#{var}) AS count").first.count > 0
  end
end
#find

Give ability to call #find on associations to get a scoped find Doesn’t pass through via method_missing because Enumerable has a #find method

def find(*args)
  scoping { @model.find(*args) }
end
#find_or_create_by

When called, this method returns a single node that satisfies the match specified in the params hash. If no existing node is found to satisfy the match, one is created or associated as expected.

def find_or_create_by(params)
  fail 'Method invalid when called on Class objects' unless source_object
  result = self.where(params).first
  return result unless result.nil?
  Neo4j::Transaction.run do
    node = model.find_or_create_by(params)
    self << node
    return node
  end
end

#first

def first(target = nil)
  first_and_last(FIRST, target)
end
#first_rel_to

Gives you the first relationship between the last link of a QueryProxy chain and a given node Shorthand for MATCH (start)-[r]-(other_node) WHERE ID(other_node) = #{other_node.neo_id} RETURN r

def first_rel_to(node)
  self.match_to(node).limit(1).pluck(rel_var).first
end

#include?

def include?(other, target = nil)
  query_with_target(target) do |var|
    where_filter = if other.respond_to?(:neo_id)
                     "ID(#{var}) = {other_node_id}"
                   else
                     "#{var}.#{association_id_key} = {other_node_id}"
                   end
    node_id = other.respond_to?(:neo_id) ? other.neo_id : other
    self.where(where_filter).params(other_node_id: node_id).query.reorder.return("count(#{var}) as count").first.count > 0
  end
end

#last

def last(target = nil)
  first_and_last(LAST, target)
end
#limit_value

TODO: update this with public API methods if/when they are exposed

def limit_value
  return unless self.query.clause?(:limit)
  limit_clause = self.query.send(:clauses).find { |clause| clause.is_a?(Neo4j::Core::QueryClauses::LimitClause) }
  limit_clause.instance_variable_get(:@arg)
end
#match_to

Shorthand for MATCH (start)-[r]-(other_node) WHERE ID(other_node) = #{other_node.neo_id} The node param can be a persisted ActiveNode instance, any string or integer, or nil. When it’s a node, it’ll use the object’s neo_id, which is fastest. When not nil, it’ll figure out the primary key of that model. When nil, it uses 1 = 2 to prevent matching all records, which is the default behavior when nil is passed to where in QueryProxy.

def match_to(node)
  first_node = node.is_a?(Array) ? node.first : node
  where_arg = if first_node.respond_to?(:neo_id)
                {neo_id: node.is_a?(Array) ? node.map(&:neo_id) : node}
              elsif !node.nil?
                {association_id_key => node.is_a?(Array) ? ids_array(node) : node}
              else
                # support for null object pattern
                '1 = 2'
              end

  self.where(where_arg)
end
#optional

A shortcut for attaching a new, optional match to the end of a QueryProxy chain.

def optional(association, node_var = nil, rel_var = nil)
  self.send(association, node_var, rel_var, optional: true)
end

#order_property

def order_property
  # This should maybe be based on a setting in the association
  # rather than a hardcoded `nil`
  model ? model.id_property_name : nil
end

#rel

def rel
  rels.first
end

#rels

def rels
  fail 'Cannot get rels without a relationship variable.' if !@rel_var

  pluck(@rel_var)
end
#rels_to

Returns all relationships across a QueryProxy chain between a given node or array of nodes and the preceeding link.

def rels_to(node)
  self.match_to(node).pluck(rel_var)
end

#size

def size
  result_cache? ? result_cache_for.length : count
end