neo4j-core 0.0.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +27 -0
- data/README.rdoc +27 -0
- data/config/neo4j/config.yml +102 -0
- data/lib/db/active_tx_log +1 -0
- data/lib/db/index/lucene-store.db +0 -0
- data/lib/db/index/lucene.log.1 +0 -0
- data/lib/db/index/lucene.log.active +0 -0
- data/lib/db/lock +0 -0
- data/lib/db/messages.log +530 -0
- data/lib/db/neostore +0 -0
- data/lib/db/neostore.id +0 -0
- data/lib/db/neostore.nodestore.db +0 -0
- data/lib/db/neostore.nodestore.db.id +0 -0
- data/lib/db/neostore.propertystore.db +0 -0
- data/lib/db/neostore.propertystore.db.arrays +0 -0
- data/lib/db/neostore.propertystore.db.arrays.id +0 -0
- data/lib/db/neostore.propertystore.db.id +0 -0
- data/lib/db/neostore.propertystore.db.index +0 -0
- data/lib/db/neostore.propertystore.db.index.id +0 -0
- data/lib/db/neostore.propertystore.db.index.keys +0 -0
- data/lib/db/neostore.propertystore.db.index.keys.id +0 -0
- data/lib/db/neostore.propertystore.db.strings +0 -0
- data/lib/db/neostore.propertystore.db.strings.id +0 -0
- data/lib/db/neostore.relationshipstore.db +0 -0
- data/lib/db/neostore.relationshipstore.db.id +0 -0
- data/lib/db/neostore.relationshiptypestore.db +0 -0
- data/lib/db/neostore.relationshiptypestore.db.id +0 -0
- data/lib/db/neostore.relationshiptypestore.db.names +0 -0
- data/lib/db/neostore.relationshiptypestore.db.names.id +0 -0
- data/lib/db/nioneo_logical.log.2 +0 -0
- data/lib/db/nioneo_logical.log.active +0 -0
- data/lib/db/tm_tx_log.1 +0 -0
- data/lib/neo4j/config.rb +139 -0
- data/lib/neo4j/cypher.rb +156 -0
- data/lib/neo4j/neo4j.rb +244 -0
- data/lib/neo4j/neo4j.rb~ +214 -0
- data/lib/neo4j/node.rb +39 -0
- data/lib/neo4j/relationship.rb +61 -0
- data/lib/neo4j/transaction.rb +86 -0
- data/lib/neo4j/type_converters/type_converters.rb +287 -0
- data/lib/neo4j-core/cypher/cypher.rb +867 -0
- data/lib/neo4j-core/cypher/result_wrapper.rb +39 -0
- data/lib/neo4j-core/database.rb +191 -0
- data/lib/neo4j-core/equal/equal.rb +23 -0
- data/lib/neo4j-core/event_handler.rb +265 -0
- data/lib/neo4j-core/index/class_methods.rb +117 -0
- data/lib/neo4j-core/index/index.rb +36 -0
- data/lib/neo4j-core/index/index_config.rb +112 -0
- data/lib/neo4j-core/index/indexer.rb +243 -0
- data/lib/neo4j-core/index/indexer_registry.rb +55 -0
- data/lib/neo4j-core/index/lucene_query.rb +264 -0
- data/lib/neo4j-core/lazy_map.rb +21 -0
- data/lib/neo4j-core/node/class_methods.rb +77 -0
- data/lib/neo4j-core/node/node.rb +47 -0
- data/lib/neo4j-core/property/property.rb +94 -0
- data/lib/neo4j-core/relationship/class_methods.rb +80 -0
- data/lib/neo4j-core/relationship/relationship.rb +97 -0
- data/lib/neo4j-core/relationship_set.rb +61 -0
- data/lib/neo4j-core/rels/rels.rb +147 -0
- data/lib/neo4j-core/rels/traverser.rb +99 -0
- data/lib/neo4j-core/to_java.rb +51 -0
- data/lib/neo4j-core/traversal/evaluator.rb +36 -0
- data/lib/neo4j-core/traversal/filter_predicate.rb +30 -0
- data/lib/neo4j-core/traversal/prune_evaluator.rb +20 -0
- data/lib/neo4j-core/traversal/rel_expander.rb +35 -0
- data/lib/neo4j-core/traversal/traversal.rb +130 -0
- data/lib/neo4j-core/traversal/traverser.rb +295 -0
- data/lib/neo4j-core/version.rb +5 -0
- data/lib/neo4j-core.rb +64 -0
- data/neo4j-core.gemspec +31 -0
- metadata +145 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Core
|
3
|
+
module Node
|
4
|
+
module ClassMethods
|
5
|
+
# Returns a new neo4j Node.
|
6
|
+
# The return node is actually an Java object of type Java::OrgNeo4jGraphdb::Node java object
|
7
|
+
# which has been extended (see the included mixins for Neo4j::Node).
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# The created node will have a unique id - Neo4j::Property#neo_id
|
11
|
+
#
|
12
|
+
# @param [Hash, Array] args either an hash of properties or an array where the first item is the database to be used and the second item is the properties
|
13
|
+
# @return [Java::OrgNeo4jGraphdb::Node] the java node which implements the Neo4j::Node mixins
|
14
|
+
#
|
15
|
+
# @example using default database
|
16
|
+
#
|
17
|
+
# Neo4j::Transaction.run do
|
18
|
+
# Neo4j::Node.new
|
19
|
+
# Neo4j::Node.new :name => 'foo', :age => 100
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# @example using a different database
|
23
|
+
#
|
24
|
+
# Neo4j::Node.new({:name => 'foo', :age => 100}, my_db)
|
25
|
+
def new(*args)
|
26
|
+
# the first argument can be an hash of properties to set
|
27
|
+
props = args[0].respond_to?(:each_pair) && args[0]
|
28
|
+
|
29
|
+
# a db instance can be given, is the first argument if that was not a hash, or otherwise the second
|
30
|
+
db = (!props && args[0]) || args[1] || Neo4j.started_db
|
31
|
+
|
32
|
+
node = db.graph.create_node
|
33
|
+
props.each_pair { |k, v| node[k]= v } if props
|
34
|
+
node
|
35
|
+
end
|
36
|
+
|
37
|
+
# create is the same as new
|
38
|
+
alias_method :create, :new
|
39
|
+
|
40
|
+
|
41
|
+
# Same as load but does not return the node as a wrapped Ruby object.
|
42
|
+
#
|
43
|
+
def _load(node_id, db = Neo4j.started_db)
|
44
|
+
return nil if node_id.nil?
|
45
|
+
db.graph.get_node_by_id(node_id.to_i)
|
46
|
+
rescue Java::OrgNeo4jGraphdb.NotFoundException
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# Checks if the given entity node or entity id (Neo4j::Node#neo_id) exists in the database.
|
52
|
+
# @return [true, false] if exist
|
53
|
+
def exist?(entity_or_entity_id, db = Neo4j.started_db)
|
54
|
+
id = entity_or_entity_id.kind_of?(Fixnum) ? entity_or_entity_id : entity_or_entity_id.id
|
55
|
+
node = _load(id, db)
|
56
|
+
return false unless node
|
57
|
+
node.has_property?('a')
|
58
|
+
true
|
59
|
+
rescue java.lang.IllegalStateException
|
60
|
+
nil # the node has been deleted
|
61
|
+
end
|
62
|
+
|
63
|
+
# Loads a node or wrapped node given a native java node or an id.
|
64
|
+
# If there is a Ruby wrapper for the node then it will create a Ruby object that will
|
65
|
+
# wrap the java node (see Neo4j::NodeMixin).
|
66
|
+
# To implement a wrapper you must implement a wrapper class method in the Neo4j::Node or Neo4j::Relationship.
|
67
|
+
#
|
68
|
+
# @return [Object, nil] If the node does not exist it will return nil otherwise the loaded node or wrapped node.
|
69
|
+
def load(node_id, db = Neo4j.started_db)
|
70
|
+
node = _load(node_id, db)
|
71
|
+
node && node.wrapper
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Neo4j
|
2
|
+
|
3
|
+
module Core
|
4
|
+
module Node
|
5
|
+
|
6
|
+
# Delete the node and all its relationship.
|
7
|
+
#
|
8
|
+
# It might raise an exception if this method was called without a Transaction,
|
9
|
+
# or if it failed to delete the node (it maybe was already deleted).
|
10
|
+
#
|
11
|
+
# If this method raise an exception you may also get an exception when the transaction finish.
|
12
|
+
# This method is defined in the Java::OrgNeo4jKernel::impl.core.NodeProxy which is return by Neo4j::Node.new
|
13
|
+
#
|
14
|
+
# @return nil or raise an exception
|
15
|
+
def del
|
16
|
+
_rels.each { |r| r.del }
|
17
|
+
delete
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# This method can be used to access the none wrapped neo4j node/relationship java object.
|
22
|
+
# Notice that this method is defined in the Java::OrgNeo4jKernel::impl.core.NodeProxy or RelationshipProxy which is return by Neo4j::Node.new
|
23
|
+
# @return the java node/relationship object representing this object unless it is already the java object.
|
24
|
+
def _java_node
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
# Same as Neo4j::Node#exist? or Neo4j::Relationship#exist?
|
29
|
+
# @return [true, false] if the node exists in the database
|
30
|
+
def exist?
|
31
|
+
Neo4j::Node.exist?(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Tries to load the wrapper object for this node by calling the class #wrapper method.
|
35
|
+
# This allows you to create a custom Ruby wrapper class around the Neo4j::Node.
|
36
|
+
# This is for example done in the <tt>neo4j<//t> ruby gem <tt>Neo4j::NodeMixin</tt>
|
37
|
+
# @return a wrapper object or self
|
38
|
+
def wrapper
|
39
|
+
self.class.respond_to?(:wrapper) ? self.class.wrapper(node) : self
|
40
|
+
end
|
41
|
+
|
42
|
+
def class
|
43
|
+
Neo4j::Node
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Core
|
3
|
+
module Property
|
4
|
+
|
5
|
+
# @return [Hash] all properties plus the id of the node with the key <tt>_neo_id</tt>
|
6
|
+
def props
|
7
|
+
ret = {"_neo_id" => neo_id}
|
8
|
+
iter = get_property_keys.iterator
|
9
|
+
while (iter.hasNext) do
|
10
|
+
key = iter.next
|
11
|
+
ret[key] = get_property(key)
|
12
|
+
end
|
13
|
+
ret
|
14
|
+
end
|
15
|
+
|
16
|
+
# Ids are garbage collected over time so they are only guaranteed to be unique during a specific time span:
|
17
|
+
# if the node is deleted, it's likely that a new node at some point will get the old id. Note:
|
18
|
+
# this makes node ids brittle as public APIs.
|
19
|
+
# @return [Fixnum] the unique id of this node.
|
20
|
+
def neo_id
|
21
|
+
getId
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param [#to_s] the property we want to check if it exist.
|
25
|
+
# @return [true false] true if the given key exist as a property.
|
26
|
+
def property?(key)
|
27
|
+
has_property?(key.to_s)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Updates this node/relationship's properties by using the provided struct/hash.
|
31
|
+
# If the option <code>{:strict => true}</code> is given, any properties present on
|
32
|
+
# the node but not present in the hash will be removed from the node.
|
33
|
+
#
|
34
|
+
# @param [Hash, :each_pair] struct_or_hash the key and value to be set
|
35
|
+
# @param [Hash] options further options defining the context of the update
|
36
|
+
# @option options [Boolean] :strict any properties present on the node but not present in the hash will be removed from the node if true
|
37
|
+
# @return self
|
38
|
+
def update(struct_or_hash, options={})
|
39
|
+
strict = options[:strict]
|
40
|
+
keys_to_delete = props.keys - %w(_neo_id _classname) if strict
|
41
|
+
struct_or_hash.each_pair do |key, value|
|
42
|
+
next if key.to_s[0..0] == '_'
|
43
|
+
# do not allow special properties to be mass assigned
|
44
|
+
keys_to_delete.delete(key.to_s) if strict
|
45
|
+
self[key] = value
|
46
|
+
end
|
47
|
+
keys_to_delete.each { |key| remove_property(key) } if strict
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# @return the value of the given key or nil if the property does not exist.
|
53
|
+
def [](key)
|
54
|
+
return unless property?(key)
|
55
|
+
val = get_property(key.to_s)
|
56
|
+
val.class.superclass == ArrayJavaProxy ? val.to_a : val
|
57
|
+
end
|
58
|
+
|
59
|
+
# Sets the property of this node.
|
60
|
+
# Property keys are always strings. Valid property value types are the primitives(<tt>String</tt>, <tt>Fixnum</tt>, <tt>Float</tt>, <tt>FalseClass</tt>, <tt>TrueClass</tt>) or array of those primitives.
|
61
|
+
#
|
62
|
+
# ==== Gotchas
|
63
|
+
# * Values in the array must be of the same type.
|
64
|
+
# * You can *not* delete or add one item in the array (e.g. person.phones.delete('123')) but instead you must create a new array instead.
|
65
|
+
#
|
66
|
+
# @param [String, Symbol] key of the property to set
|
67
|
+
# @param [String,Fixnum,Float,true,false, Array] value to set
|
68
|
+
def []=(key, value)
|
69
|
+
k = key.to_s
|
70
|
+
if value.nil?
|
71
|
+
remove_property(k)
|
72
|
+
elsif (Array === value)
|
73
|
+
case value[0]
|
74
|
+
when NilClass
|
75
|
+
set_property(k, [].to_java(:string))
|
76
|
+
when String
|
77
|
+
set_property(k, value.to_java(:string))
|
78
|
+
when Float
|
79
|
+
set_property(k, value.to_java(:double))
|
80
|
+
when FalseClass, TrueClass
|
81
|
+
set_property(k, value.to_java(:boolean))
|
82
|
+
when Fixnum
|
83
|
+
set_property(k, value.to_java(:long))
|
84
|
+
else
|
85
|
+
raise "Not allowed to store array with value #{value[0]} type #{value[0].class}"
|
86
|
+
end
|
87
|
+
else
|
88
|
+
set_property(k, value)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Core
|
3
|
+
module Relationship
|
4
|
+
module ClassMethods
|
5
|
+
|
6
|
+
# Returns a Java::OrgNeo4jGraphdb::Relationship java object which include the Neo4j::Relationship mixins.
|
7
|
+
# Will trigger a event that the relationship was created.
|
8
|
+
#
|
9
|
+
# @param [String, Symbol] type of relationship
|
10
|
+
# @param [#_java_node] from_node the start node of this relationship
|
11
|
+
# @param [#_java_node] end_node the end node of this relationship
|
12
|
+
# @param [Hash] props optional properties for the created relationship
|
13
|
+
#
|
14
|
+
# @return [Neo4j::Relationship] which is really a Java::OrgNeo4jGraphdb::Relationship java object including the Neo4j::Relationship mixins
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
#
|
18
|
+
# Neo4j::Relationship.new :friend, node1, node2, :since => '2001-01-02', :status => 'okey'
|
19
|
+
#
|
20
|
+
def new(type, start_node, end_node, props=nil)
|
21
|
+
java_type = ToJava.type_to_java(type)
|
22
|
+
rel = start_node._java_node.create_relationship_to(end_node._java_node, java_type)
|
23
|
+
props.each_pair { |k, v| rel[k] = v } if props
|
24
|
+
rel
|
25
|
+
end
|
26
|
+
|
27
|
+
# create is the same as new
|
28
|
+
alias_method :create, :new
|
29
|
+
|
30
|
+
# Loads a relationship or wrapped relationship given a native java relationship or an id.
|
31
|
+
# If there is a Ruby wrapper for the node then it will create a Ruby object that will
|
32
|
+
# wrap the java node (see Neo4j::RelationshipMixin).
|
33
|
+
# Notice that it can load the node even if it has been deleted in the same transaction, see #exist?
|
34
|
+
#
|
35
|
+
# @see #_load
|
36
|
+
# @see #exist?
|
37
|
+
# @return the wrapper for the relationship or nil
|
38
|
+
def load(rel_id, db = Neo4j.started_db)
|
39
|
+
rel = _load(rel_id, db)
|
40
|
+
return nil if rel.nil?
|
41
|
+
rel.wrapper
|
42
|
+
end
|
43
|
+
|
44
|
+
# Same as load but does not return the node as a wrapped Ruby object.
|
45
|
+
# @see #load
|
46
|
+
def _load(rel_id, db = Neo4j.started_db)
|
47
|
+
return nil if rel_id.nil?
|
48
|
+
rel = db.graph.get_relationship_by_id(rel_id.to_i)
|
49
|
+
# TODO
|
50
|
+
rel
|
51
|
+
rescue Java::OrgNeo4jGraphdb::NotFoundException
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
# Checks if the given node or entity id (Neo4j::Relationship#neo_id) exists in the database.
|
56
|
+
# @return [true, false] if exist
|
57
|
+
def exist?(entity_or_entity_id, db = Neo4j.started_db)
|
58
|
+
id = entity_or_entity_id.kind_of?(Fixnum) ? entity_or_entity_id : entity_or_entity_id.id
|
59
|
+
entity = _load(id, db)
|
60
|
+
return false unless entity
|
61
|
+
entity.hasProperty('_classname') # since we want a IllegalStateException which is otherwise not triggered
|
62
|
+
true
|
63
|
+
rescue java.lang.IllegalStateException
|
64
|
+
nil # the node has been deleted
|
65
|
+
end
|
66
|
+
|
67
|
+
# Loads a relationship or wrapped relationship given a native java relationship or an id.
|
68
|
+
# If there is a Ruby wrapper for the relationship then it will create a Ruby object that will
|
69
|
+
# wrap the java node (see Neo4j::RelationshipMixin).
|
70
|
+
# To implement a wrapper you must implement a wrapper class method in the Neo4j::Node or Neo4j::Relationship.
|
71
|
+
#
|
72
|
+
# @return [Object, nil] If the node does not exist it will return nil otherwise the loaded node or wrapped node.
|
73
|
+
def load(node_id, db = Neo4j.started_db)
|
74
|
+
node = _load(node_id, db)
|
75
|
+
node && node.wrapper
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Core
|
3
|
+
module Relationship
|
4
|
+
|
5
|
+
# Same as Java::OrgNeo4jGraphdb::Relationship#getEndNode
|
6
|
+
def _end_node
|
7
|
+
get_end_node
|
8
|
+
end
|
9
|
+
|
10
|
+
# Same as Java::OrgNeo4jGraphdb::Relationship#getStartNode
|
11
|
+
def _start_node
|
12
|
+
get_start_node
|
13
|
+
end
|
14
|
+
|
15
|
+
# Same as Java::OrgNeo4jGraphdb::Relationship#getOtherNode
|
16
|
+
def _other_node(node)
|
17
|
+
get_other_node(node)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Deletes the relationship between the start and end node
|
21
|
+
# May raise an exception if delete was unsuccessful.
|
22
|
+
#
|
23
|
+
# @return [nil]
|
24
|
+
def del
|
25
|
+
delete
|
26
|
+
end
|
27
|
+
|
28
|
+
# Same as Java::OrgNeo4jGraphdb::Relationship#getEndNode but returns the wrapper for it (if it exist)
|
29
|
+
# @see Neo4j::Node#wrapper
|
30
|
+
def end_node
|
31
|
+
_end_node.wrapper
|
32
|
+
end
|
33
|
+
|
34
|
+
# Same as Java::OrgNeo4jGraphdb::Relationship#getStartNode but returns the wrapper for it (if it exist)
|
35
|
+
# @see Neo4j::Node#wrapper
|
36
|
+
def start_node
|
37
|
+
_start_node.wrapper
|
38
|
+
end
|
39
|
+
|
40
|
+
# A convenience operation that, given a node that is attached to this relationship, returns the other node.
|
41
|
+
# For example if node is a start node, the end node will be returned, and vice versa.
|
42
|
+
# This is a very convenient operation when you're manually traversing the node space by invoking one of the #rels
|
43
|
+
# method on a node. For example, to get the node "at the other end" of a relationship, use the following:
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# end_node = node.rels.first.other_node(node)
|
47
|
+
#
|
48
|
+
# @raise This operation will throw a runtime exception if node is neither this relationship's start node nor its end node.
|
49
|
+
#
|
50
|
+
# @param [Neo4j::Node] node the node that we don't want to return
|
51
|
+
# @return [Neo4j::Node] the other node wrapper
|
52
|
+
def other_node(node)
|
53
|
+
_other_node(node._java_node).wrapper
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# same as #_java_rel
|
58
|
+
# Used so that we have same method for both relationship and nodes
|
59
|
+
def wrapped_entity
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return self
|
64
|
+
def _java_rel
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [true, false] if the relationship exists
|
69
|
+
def exist?
|
70
|
+
Neo4j::Relationship.exist?(self)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Loads the wrapper using the #wrapper class method if it exists, otherwise return self.
|
74
|
+
def wrapper
|
75
|
+
self.class.respond_to?(:wrapper) ? self.class.wrapper(node) : self
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# Returns the relationship name
|
80
|
+
#
|
81
|
+
# @example
|
82
|
+
# a = Neo4j::Node.new
|
83
|
+
# a.outgoing(:friends) << Neo4j::Node.new
|
84
|
+
# a.rels.first.rel_type # => 'friends'
|
85
|
+
# @return [String] the type of the relationship
|
86
|
+
def rel_type
|
87
|
+
getType().name()
|
88
|
+
end
|
89
|
+
|
90
|
+
def class
|
91
|
+
Neo4j::Relationship
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Core
|
3
|
+
# == Represents a set of relationships.
|
4
|
+
# See Neo4j::EventHandler
|
5
|
+
class RelationshipSet
|
6
|
+
def initialize(size=0)
|
7
|
+
@relationship_type_set = java.util.HashSet.new(size)
|
8
|
+
@relationship_set = java.util.HashSet.new(size)
|
9
|
+
@relationship_map = java.util.HashMap.new(size)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Adds a relationship to the set
|
13
|
+
def add(rel)
|
14
|
+
@relationship_type_set.add(RelationshipSetEntry.new(rel.getEndNode().getId(), rel.rel_type))
|
15
|
+
relationships(rel.getEndNode().getId()) << rel
|
16
|
+
@relationship_set.add(rel.getId)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns a collection of relationships where the node with the specified end node id is the end node.
|
20
|
+
def relationships(end_node_id)
|
21
|
+
@relationship_map.get(end_node_id) || add_list(end_node_id)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns true if the specified relationship is in the set
|
25
|
+
def contains_rel?(rel)
|
26
|
+
@relationship_set.contains(rel.getId)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns true if a relationship with the specified end_node_id and relationship_type is present in the set.
|
30
|
+
def contains?(end_node_id, relationship_type)
|
31
|
+
@relationship_type_set.contains(RelationshipSetEntry.new(end_node_id, relationship_type))
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
def add_list(node_id)
|
36
|
+
@relationship_map.put(node_id, [])
|
37
|
+
@relationship_map.get(node_id)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class RelationshipSetEntry
|
42
|
+
attr_accessor :nodeid, :relationship_type
|
43
|
+
|
44
|
+
def initialize(nodeid, relationship_type)
|
45
|
+
@nodeid, @relationship_type = nodeid.to_s, relationship_type.to_s
|
46
|
+
end
|
47
|
+
|
48
|
+
def ==(o)
|
49
|
+
eql?(o)
|
50
|
+
end
|
51
|
+
|
52
|
+
def eql?(other)
|
53
|
+
@nodeid == other.nodeid && @relationship_type == other.relationship_type
|
54
|
+
end
|
55
|
+
|
56
|
+
def hash
|
57
|
+
3 * @nodeid.hash + @relationship_type.hash
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Core
|
3
|
+
# Contains methods for traversing relationship object of depth one from one node.
|
4
|
+
module Rels
|
5
|
+
# Returns the only node of a given type and direction that is attached to this node, or nil.
|
6
|
+
# This is a convenience method that is used in the commonly occuring situation where a node has exactly zero or one relationships of a given type and direction to another node.
|
7
|
+
# Typically this invariant is maintained by the rest of the code: if at any time more than one such relationships exist, it is a fatal error that should generate an exception.
|
8
|
+
|
9
|
+
# This method reflects that semantics and returns either:
|
10
|
+
# * nil if there are zero relationships of the given type and direction,
|
11
|
+
# * the relationship if there's exactly one, or
|
12
|
+
# * throws an unchecked exception in all other cases.
|
13
|
+
#
|
14
|
+
# This method should be used only in situations with an invariant as described above. In those situations, a "state-checking" method (e.g. #rel?) is not required,
|
15
|
+
# because this method behaves correctly "out of the box."
|
16
|
+
#
|
17
|
+
# @param (see #rel)
|
18
|
+
# @see Neo4j::Core::Node#wrapper #wrapper - The method used to wrap the node in a Ruby object if the node was found
|
19
|
+
def node(dir, type)
|
20
|
+
n = _node(dir, type)
|
21
|
+
n && n.wrapper
|
22
|
+
end
|
23
|
+
|
24
|
+
# Same as #node but instead returns an unwrapped native java node.
|
25
|
+
# @param (see #rel)
|
26
|
+
def _node(dir, type)
|
27
|
+
r = _rel(dir, type)
|
28
|
+
r && r._other_node(self._java_node)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Works like #rels method but instead returns the nodes.
|
32
|
+
# @param (see #rels)
|
33
|
+
# @see #rels
|
34
|
+
# @return [Enumerable<Neo4j::Node>]
|
35
|
+
def _nodes(dir, *types)
|
36
|
+
r = _rels(dir, *types)
|
37
|
+
case dir
|
38
|
+
when :outgoing then
|
39
|
+
Neo4j::Core::LazyMap.new(r, &:_end_node)
|
40
|
+
when :incoming then
|
41
|
+
Neo4j::Core::LazyMap.new(r, &:_start_node)
|
42
|
+
when :both then
|
43
|
+
Neo4j::Core::LazyMap.new(r) { |x| x._other_node(self) }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Works like #rels method but instead returns the nodes.
|
48
|
+
# It does try to load a Ruby wrapper around each node
|
49
|
+
# @param (see #rels)
|
50
|
+
# @see Neo4j::Core::Node#wrapper #wrapper - The method used wrap to the node in a Ruby object if the node was found
|
51
|
+
# @return [Enumerable] an Enumeration of either Neo4j::Node objects or wrapped Neo4j::Node objects
|
52
|
+
# @notice it's possible that the same node is returned more then once because of several relationship reaching to the same node, see #outgoing for alternative
|
53
|
+
def nodes(dir, *types)
|
54
|
+
Neo4j::Core::LazyMap.new(_nodes(dir, *types), &:wrapper)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# Returns an enumeration of relationship objects using the builder DSL pattern.
|
59
|
+
# It always returns relationships of depth one.
|
60
|
+
#
|
61
|
+
# @param [:both, :incoming, :outgoing] dir the direction of the relationship
|
62
|
+
# @param [String, Symbol] types the requested relationship types we want look for, if none it gets relationships of any type
|
63
|
+
# @return [Neo4j::Core::Rels::Traverser] an object which included the Ruby Enumerable mixin
|
64
|
+
#
|
65
|
+
# @example Return both incoming and outgoing relationships
|
66
|
+
# me.rels(:both, :friends, :work).each {|relationship|...}
|
67
|
+
#
|
68
|
+
# @example Only return outgoing relationship of given type
|
69
|
+
# me.rels(:outgoing, :friends).first.end_node # => my friend node
|
70
|
+
#
|
71
|
+
# @example All the relationships between me and another node of given dir & type
|
72
|
+
# me.rels(:outgoing, :friends).to_other(node)
|
73
|
+
#
|
74
|
+
# @example Delete all relationships between me and another node of given dir & type
|
75
|
+
# me.rels(:outgoing, :friends).to_other(node).del
|
76
|
+
#
|
77
|
+
# @see Neo4j::Core::Node#wrapper #wrapper - The method used wrap to the node in a Ruby object if the node was found
|
78
|
+
# @see Neo4j::Relationship#rel_type
|
79
|
+
# @raise an exception if the first parameter is not <tt>:both</tt>, <tt>;outgoing</tt> or <tt>:incoming</tt>
|
80
|
+
def rels(dir=:both, *types)
|
81
|
+
raise "Illegal argument, first argument must be :both, :incoming or :outgoing, got #{dir.inspect}" unless [:incoming, :outgoing, :both].include?(dir)
|
82
|
+
Neo4j::Core::Rels::Traverser.new(self, types, dir)
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
# Returns the only relationship of a given type and direction that is attached to this node, or null.
|
87
|
+
# This is a convenience method that is used in the commonly occuring situation where a node has exactly zero or
|
88
|
+
# one relationships of a given type and direction to another node.
|
89
|
+
# Typically this invariant is maintained by the rest of the code: if at any time more than one such relationships
|
90
|
+
# exist, it is a fatal error that should generate an unchecked exception. This method reflects that semantics and
|
91
|
+
# returns either:
|
92
|
+
#
|
93
|
+
# * nil if there are zero relationships of the given type and direction,
|
94
|
+
# * the relationship if there's exactly one, or
|
95
|
+
# * raise an exception in all other cases.
|
96
|
+
# @param [:both, :incoming, :outgoing] dir the direction of the relationship
|
97
|
+
# @param [Symbol, String] type the type of relationship, see Neo4j::Core::Relationship#rel_type
|
98
|
+
# @return [Neo4j::Relationship, nil, Object] the Relationship or wrapper for the Relationship or nil
|
99
|
+
# @see Neo4j::Core::Relationship#rel_type
|
100
|
+
# @see Neo4j::Core::Node#wrapper #wrapper - The method used to wrap the node in a Ruby object if the node was found
|
101
|
+
def rel(dir, type)
|
102
|
+
result = _rel(dir, type)
|
103
|
+
result && result.wrapper
|
104
|
+
end
|
105
|
+
|
106
|
+
# Same as rel but does not return a ruby wrapped object but instead returns the Java object.
|
107
|
+
# @param (see #rel)
|
108
|
+
# @return [Neo4j::Relationship, nil]
|
109
|
+
# @see #rel
|
110
|
+
def _rel(dir, type)
|
111
|
+
get_single_relationship(ToJava.type_to_java(type), ToJava.dir_to_java(dir))
|
112
|
+
end
|
113
|
+
|
114
|
+
# Finds relationship starting from this node given a direction and/or relationship type(s).
|
115
|
+
# @param (see #rels)
|
116
|
+
# @return [Enumerable] of Neo4j::Relationship objects
|
117
|
+
def _rels(dir=:both, *types)
|
118
|
+
if types.size > 1
|
119
|
+
get_relationships(ToJava.dir_to_java(dir), ToJava.types_to_java(types))
|
120
|
+
elsif types.size == 1
|
121
|
+
get_relationships(ToJava.type_to_java(types[0]), ToJava.dir_to_java(dir))
|
122
|
+
else
|
123
|
+
get_relationships(ToJava.dir_to_java(dir))
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Check if the given relationship exists
|
128
|
+
# Returns true if there are one or more relationships from this node to other nodes
|
129
|
+
# with the given relationship.
|
130
|
+
#
|
131
|
+
# @param [:both, :incoming, :outgoing] dir optional default :both (either, :outgoing, :incoming, :both)
|
132
|
+
# @param [String,Symbol] type the key and value to be set, default any type
|
133
|
+
# @return [Boolean] true if one or more relationships exists for the given type and dir otherwise false
|
134
|
+
def rel?(dir=:both, type=nil)
|
135
|
+
if type
|
136
|
+
has_relationship(ToJava.type_to_java(type), ToJava.dir_to_java(dir))
|
137
|
+
else
|
138
|
+
has_relationship(ToJava.dir_to_java(dir))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
end
|