lib/neo4j/active_node/labels.rb in neo4j-3.0.0.alpha.8 vs lib/neo4j/active_node/labels.rb in neo4j-3.0.0.alpha.9

- old
+ new

@@ -57,69 +57,97 @@ end end end module ClassMethods - # Find all nodes/objects of this class def all self.query_as(:n).pluck(:n) end + # Returns the first node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. def first - self.query_as(:n).limit(1).order('n.neo_id').pluck(:n).first + self.query_as(:n).limit(1).order('ID(n)').pluck(:n).first end + # Returns the last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs. def last - count = self.count - final_count = count == 0 ? 0 : count - 1 - self.query_as(:n).order('n.neo_id').skip(final_count).limit(1).pluck(:n).first + self.query_as(:n).order('ID(n) DESC').limit(1).pluck(:n).first end # @return [Fixnum] number of nodes of this class def count self.query_as(:n).return("count(n) AS count").first.count end # Returns the object with the specified neo4j id. - # @param [String,Fixnum] neo_id of node to find + # @param [String,Fixnum] id of node to find def find(id) - raise "Unknown argument #{id.class} in find method" if not [String, Fixnum].include?(id.class) - - Neo4j::Node.load(id.to_i) + raise "Unknown argument #{id.class} in find method (expected String or Fixnum)" if not [String, Fixnum].include?(id.class) + find_by_id(id) end # Finds the first record matching the specified conditions. There is no implied ordering so if order matters, you should specify it yourself. - # @param [Hash] hash of arguments to find + # @param [Hash] args of arguments to find def find_by(*args) self.query_as(:n).where(n: eval(args.join)).limit(1).pluck(:n).first end # Like find_by, except that if no record is found, raises a RecordNotFound error. def find_by!(*args) a = eval(args.join) find_by(args) or raise RecordNotFound, "#{self.query_as(:n).where(n: a).limit(1).to_cypher} returned no results" end - # Destroy all nodes an connected relationships + # Destroy all nodes and connected relationships def destroy_all self.neo4j_session._query("MATCH (n:`#{mapped_label_name}`)-[r]-() DELETE n,r") self.neo4j_session._query("MATCH (n:`#{mapped_label_name}`) DELETE n") end # Creates a Neo4j index on given property + # + # This can also be done on the property directly, see Neo4j::ActiveNode::Property::ClassMethods#property. + # # @param [Symbol] property the property we want a Neo4j index on - def index(property) - if self.neo4j_session - _index(property) - else - Neo4j::Session.add_listener do |event, _| - _index(property) if event == :session_available - end + # @param [Hash] conf optional property configuration + # + # @example + # class Person + # include Neo4j::ActiveNode + # property :name + # index :name + # end + # + # @example with constraint + # class Person + # include Neo4j::ActiveNode + # property :name + # + # # below is same as: index :name, index: :exact, constraint: {type: :unique} + # index :name, constraint: {type: :unique} + # end + def index(property, conf = {}) + Neo4j::Session.on_session_available do |_| + _index(property, conf) end + @_indexed_properties ||= [] + @_indexed_properties.push property unless @_indexed_properties.include? property end + # Creates a neo4j constraint on this class for given property + # + # @example + # Person.constraint :name, type: :unique + # + def constraint(property, constraints, session = Neo4j::Session.current) + Neo4j::Session.on_session_available do |_| + label = Neo4j::Label.create(mapped_label_name) + label.create_constraint(property, constraints, session) + end + end + def index?(index_def) mapped_label.indexes[:property_keys].include?(index_def) end # @return [Array{Symbol}] all the labels that this class has @@ -130,29 +158,38 @@ # @return [Symbol] the label that this class has which corresponds to a Ruby class def mapped_label_name @_label_name || self.to_s.to_sym end - def indexed_labels + # @return [Neo4j::Label] the label for this class + def mapped_label + Neo4j::Label.create(mapped_label_name) + end + def indexed_properties + @_indexed_properties end + protected - def _index(property) + def _index(property, conf) mapped_labels.each do |label| # make sure the property is not indexed twice existing = label.indexes[:property_keys] - label.create_index(property) unless existing.flatten.include?(property) + + # In neo4j constraint automatically creates an index + if conf[:constraint] + constraint(property, conf[:constraint]) + else + label.create_index(property) unless existing.flatten.include?(property) + end + end end def mapped_labels mapped_label_names.map{|label_name| Neo4j::Label.create(label_name)} - end - - def mapped_label - Neo4j::Label.create(mapped_label_name) end def set_mapped_label_name(name) @_label_name = name.to_sym end