Navigation Menu

Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/andreasronge/neo4j
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Kleppmann committed Jun 17, 2009
2 parents 17d75d7 + 5762bf2 commit df1cd9a
Show file tree
Hide file tree
Showing 37 changed files with 978 additions and 639 deletions.
61 changes: 38 additions & 23 deletions README.rdoc
Expand Up @@ -27,6 +27,7 @@ It uses two powerful and mature java libraries:
* Twitter - http://twitter.com/ronge
* API Yard Documentation - http://neo4j.rubyforge.org/
* Source repo - git://github.com/andreasronge/neo4j.git
* Mailing list - https://lists.neo4j.org/mailman/listinfo/user

=== Presentation Materials and other URLs
* Ruby Manor 2008 - Jonathan Conway: http://jaikoo.com/assets/presentations/neo4j.pdf
Expand Down Expand Up @@ -75,12 +76,34 @@ a social network, a relationship type could be KNOWS. If a relationship of the t
that probably represents two people that know each other. A lot of the semantics, the meaning, of a node space
is encoded in the relationship types of the application.

=== Creating Nodes

Example of creating a neo4j node:

require "rubygems"
require 'neo4j'

node = Neo4j::Node.new
Neo4j::Transaction.run do
node = Neo4j::Node.new
end

=== Transactions

Almost all Neo4j operation must be wrapped in a transaction as shown above.
In the following examples we assume that the operations are inside an Neo4j transaction.
Neo4j.rb supports auto commits without wrapping Neo4j operations in Neo4j::Transactions.
To enable that require the file 'neo4j/auto_tx' instead of 'neo4j'

Example

require 'neo4j/auto_tx'

# no need to wrap operations in Neo4j::Transaction.run do .. end
Node.new

This feature should be used for testing and development purpose.

=== Setting Properties

Example of setting properties

Expand All @@ -90,16 +113,20 @@ Example of setting properties
node[:hungry] = false
node[4] = 3.14

=== Getting Properties
Example of getting properties

node[:name] # => 'foo'


=== Creating Relationships
Example of creating a relationship

node1 = Neo4j::Node.new
node2 = Neo4j::Node.new
node1.relationships.outgoing(:friends) << node2 # connects node1 to node2 with relationship type 'friends'

=== Accessing Relationships
Example of getting relationships

node1.relationships.empty? # => false
Expand All @@ -113,12 +140,14 @@ Example of getting relationships
node1.relationships.incoming(:friends).nodes.first # => node1 first node of relationship type 'friends'
node2.relationships.incoming(:friends).first # => a relationship object between node1 and node2

=== Properties on Relationships
Example of setting properties on relationships

rel = node1.relationships(:friends).first
rel[:since] = 1982
node1.relationships.first[:since] # => 1982 (there is only one relationship defined on node1 in this example)

=== The Node and NodeMixin
Here is the complete implemenation of the Neo4j::Node class

module Neo4j
Expand Down Expand Up @@ -624,10 +653,7 @@ Example of how declare a class that has this behaviour:

=== Create a Node

If a block is provided then the creation of the instance will be performed in an
transaction, see below for more information on transactions.

node = MyNode.new { }
node = MyNode.new

=== Delete a Node

Expand Down Expand Up @@ -1116,8 +1142,6 @@ Notice there is also a otherway of finding nodes, see the Neo4j::NodeMixin#trave
=== Transactions

All operations that work with the node space (even read operations) must be wrapped in a transaction.
Luckly neo4j.rb will automatically create a transaction for those operation that needs it if one is not already provided.

For example all get, set and find operations will start a new transaction if none is already not runnig (for that thread).

If you want to perform a set of operation in a single transaction, use the Neo4j::Transaction.run method:
Expand All @@ -1129,21 +1153,8 @@ Example
node2.bar = "hi"
}

There is also a TransactionalMixin that lets you declare which method should be wrapped inside a transaction.
Example:

class Person
include Neo4j::NodeMixin
extend Neo4j::TransactionalMixin

property :name, :age

def do_stuff
# ... no transaction stuff needed to be written here.
end

transactional :do_stuff
end
There is also a auto commit feature available which is enabled by requiring 'neo4j/auto_tx' instead of 'neo4j',
see the three minutes tutorial above.

==== Rollback

Expand Down Expand Up @@ -1181,7 +1192,7 @@ For example to index the proeprties foo and bar

Everytime a node of type SomeNode (or a subclass) is create, deleted or updated the lucene index of will be updated.

=== Updating Lucene Index
=== Reindexing

Sometimes it's neccessarly to change the index of a class after alot of node instances already have been created.
To delete an index use the class method 'remove_index'
Expand Down Expand Up @@ -1213,6 +1224,10 @@ In order to use the update_index method you must include the reindexer neo4j.rb
This extensions will keep a relationship to each created node so that it later can recreate
the index by traversing those relationships.

=== Updating Lucene Index

The lucene index will be updated after the transaction commits. It is not possible to
query for something that has been created inside the same transaction as where the query is performed.

=== Quering (using lucene)

Expand Down
3 changes: 2 additions & 1 deletion examples/imdb/find_actors.rb
@@ -1,6 +1,7 @@
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../../lib")
#require "rubygems"
require "neo4j"
require "neo4j"
require "neo4j/extensions/reindexer"
require "model"

Neo4j::Config[:storage_path] = DB_NEO_DIR
Expand Down
5 changes: 5 additions & 0 deletions lib/neo4j/auto_tx.rb
@@ -0,0 +1,5 @@

NEO4J_AUTO_TX = true
loaded = require 'neo4j'
puts "LOADED" if loaded
puts "NOT LOADED" unless loaded
Expand Up @@ -13,7 +13,7 @@ def update_index
n.update_index
end
end

# Returns node instances of this class.
#
# :api: public
Expand Down Expand Up @@ -78,6 +78,11 @@ def self.instance


# Add this so it can add it self as listener
Neo4j.event_handler.add(IndexNode)
def self.load_reindexer
Neo4j.event_handler.add(IndexNode)
# incase we already have started
Neo4j::Transaction.run { IndexNode.on_neo_started(Neo4j.instance) } if Neo4j.running?
end

load_reindexer
end
Expand Up @@ -57,6 +57,7 @@ def on_property_changed(node, key, old_value, new_value)

def undo_tx
tx_node = tx_nodes.first
return if (tx_node.nil?)
tracked_node_id = tx_node[:tracked_node_id]

if (tx_node[:created])
Expand Down Expand Up @@ -125,9 +126,13 @@ def to_s
end

# Add this so it can add it self as listener
Neo4j.event_handler.add_filter(TxNode)
Neo4j.event_handler.add_filter(TxNodeCreated)
Neo4j.event_handler.add(TxNodeList)
def self.load_tx_tracker
Neo4j.event_handler.add_filter(TxNode)
Neo4j.event_handler.add_filter(TxNodeCreated)
Neo4j.event_handler.add(TxNodeList)

Neo4j::Transaction.run { TxNodeList.on_neo_started(Neo4j.instance) } if Neo4j.running?
end

# if neo is already run we have to let txnodelist have a chance to add it self
# TxNodeList.on_neo_started(Neo4j.instance) if Neo4j.running?
Expand All @@ -147,4 +152,7 @@ def self.load_uuid(uuid)

# if it does not exist we need to create a new node
end

load_tx_tracker

end
20 changes: 7 additions & 13 deletions lib/neo4j/mixins/node.rb
Expand Up @@ -20,7 +20,6 @@ module NodeMixin

# Initialize the the neo node for this instance.
# Will create a new transaction if one is not already running.
# If a block is given a new transaction will be created.
#
# Does
# * sets the neo property 'classname' to self.class.to_s
Expand All @@ -29,13 +28,11 @@ module NodeMixin
# :api: public
def initialize(*args)
# was a neo java node provided ?
Transaction.run do
if args.length == 1 and args[0].kind_of?(org.neo4j.api.core.Node)
init_with_node(args[0])
else
init_without_node
yield self if block_given?
end
if args.length == 1 and args[0].kind_of?(org.neo4j.api.core.Node)
init_with_node(args[0])
else
init_without_node
init_node(*args) if self.respond_to?(:init_node)
end
# must call super with no arguments so that chaining of initialize method will work
super()
Expand Down Expand Up @@ -80,7 +77,7 @@ def init_without_node
def set_property(name, value)
$NEO_LOGGER.debug{"set property '#{name}'='#{value}'"}
old_value = get_property(name)

if value.nil?
remove_property(name)
elsif self.class.marshal?(name)
Expand Down Expand Up @@ -290,7 +287,6 @@ def relationships
end



# Check if the given relationship exists
# Returns true if there are one or more relationships from this node to other nodes
# with the given relationship.
Expand Down Expand Up @@ -347,7 +343,7 @@ def update_index
end


transactional :property?, :set_property, :get_property, :remove_property, :delete
transactional :initialize, :property?, :set_property, :get_property, :remove_property, :delete


#
Expand Down Expand Up @@ -564,7 +560,6 @@ def remove_index(*keys)
end



# :api: private
def index_property(prop)
indexer.add_index_on_property(prop)
Expand Down Expand Up @@ -637,7 +632,6 @@ def #{rel_type}(&block)
end



# Creates a new outgoing relationship.
#
# :api: private
Expand Down
5 changes: 2 additions & 3 deletions lib/neo4j/mixins/relationship.rb
Expand Up @@ -15,8 +15,7 @@ module RelationshipMixin
#
# :api: public
def initialize(*args)
Transaction.run {init_with_rel(args[0])} unless Transaction.running?
init_with_rel(args[0]) if Transaction.running?
init_with_rel(args[0])

# must call super with no arguments so that chaining of initialize method will work
super()
Expand Down Expand Up @@ -117,7 +116,7 @@ def neo_relationship_id
@internal_r.getId()
end

transactional :property?, :set_property, :get_property, :delete
transactional :initialize, :property?, :set_property, :get_property, :delete

#
# Adds classmethods in the ClassMethods module
Expand Down
4 changes: 3 additions & 1 deletion lib/neo4j/mixins/transactional.rb
Expand Up @@ -2,11 +2,13 @@ module Neo4j

#
# Includes support for wrapping a method in a Neo4j transaction.
# If the constant NEO4J_AUTO_TX is defined then the specified methods will be wrapped in a transaction.
#
module TransactionalMixin

def transactional(*methods)
# return unless (Neo4j::Config[:auto_tx])
return unless defined? NEO4J_AUTO_TX
puts "transactional: #{methods.inspect}"
methods.each do |name|
orig_name = (name.to_s == '<<') ? '_append' : "_original_#{name}"
self.send :alias_method, orig_name, name
Expand Down
12 changes: 6 additions & 6 deletions lib/neo4j/neo.rb
Expand Up @@ -91,7 +91,7 @@ def self.event_handler
@event_handler ||= EventHandler.new
end


#
# Allows run and stop the Neo4j service
# Contains global ćonstants such as location of the neo storage and index files
Expand All @@ -101,6 +101,8 @@ def self.event_handler
#
class Neo

extend Neo4j::TransactionalMixin

#
# ref_node : the reference, ReferenceNode, node, wraps a org.neo4j.api.core.NeoService#getReferenceNode
#
Expand All @@ -114,7 +116,6 @@ def start
Neo4j.event_handler.neo_started(self)
end
$NEO_LOGGER.info{ "Started neo. Database storage located at '#{@db_storage}'"}

end

#
Expand All @@ -139,10 +140,8 @@ def begin_transaction
#
def find_node(id)
begin
Transaction.run do
neo_node = @neo.getNodeById(id)
load_node(neo_node)
end
neo_node = @neo.getNodeById(id)
load_node(neo_node)
rescue org.neo4j.api.core.NotFoundException
nil
end
Expand Down Expand Up @@ -194,6 +193,7 @@ def tx_manager
@neo.getConfig().getTxModule().getTxManager()
end

transactional :find_node

end
end
Expand Down

0 comments on commit df1cd9a

Please sign in to comment.