neography-down 1.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.project +12 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +4 -0
  6. data/CHANGELOG.md +939 -0
  7. data/CONTRIBUTORS +18 -0
  8. data/Gemfile +4 -0
  9. data/Guardfile +14 -0
  10. data/LICENSE +19 -0
  11. data/README.md +281 -0
  12. data/Rakefile +14 -0
  13. data/examples/facebook.rb +40 -0
  14. data/examples/facebook_v2.rb +25 -0
  15. data/examples/greatest.rb +43 -0
  16. data/examples/linkedin.rb +39 -0
  17. data/examples/linkedin_v2.rb +22 -0
  18. data/examples/traversal_example1.rb +65 -0
  19. data/examples/traversal_example2.rb +54 -0
  20. data/lib/neography.rb +45 -0
  21. data/lib/neography/config.rb +64 -0
  22. data/lib/neography/connection.rb +263 -0
  23. data/lib/neography/equal.rb +21 -0
  24. data/lib/neography/errors.rb +60 -0
  25. data/lib/neography/index.rb +52 -0
  26. data/lib/neography/multi_json_parser.rb +28 -0
  27. data/lib/neography/neography.rb +10 -0
  28. data/lib/neography/node.rb +63 -0
  29. data/lib/neography/node_path.rb +29 -0
  30. data/lib/neography/node_relationship.rb +37 -0
  31. data/lib/neography/node_traverser.rb +146 -0
  32. data/lib/neography/path_traverser.rb +100 -0
  33. data/lib/neography/property.rb +110 -0
  34. data/lib/neography/property_container.rb +28 -0
  35. data/lib/neography/railtie.rb +19 -0
  36. data/lib/neography/relationship.rb +78 -0
  37. data/lib/neography/relationship_traverser.rb +80 -0
  38. data/lib/neography/rest.rb +99 -0
  39. data/lib/neography/rest/batch.rb +414 -0
  40. data/lib/neography/rest/clean.rb +17 -0
  41. data/lib/neography/rest/constraints.rb +38 -0
  42. data/lib/neography/rest/cypher.rb +29 -0
  43. data/lib/neography/rest/extensions.rb +21 -0
  44. data/lib/neography/rest/gremlin.rb +20 -0
  45. data/lib/neography/rest/helpers.rb +96 -0
  46. data/lib/neography/rest/node_auto_indexes.rb +60 -0
  47. data/lib/neography/rest/node_indexes.rb +139 -0
  48. data/lib/neography/rest/node_labels.rb +49 -0
  49. data/lib/neography/rest/node_paths.rb +49 -0
  50. data/lib/neography/rest/node_properties.rb +52 -0
  51. data/lib/neography/rest/node_relationships.rb +33 -0
  52. data/lib/neography/rest/node_traversal.rb +25 -0
  53. data/lib/neography/rest/nodes.rb +94 -0
  54. data/lib/neography/rest/other_node_relationships.rb +38 -0
  55. data/lib/neography/rest/relationship_auto_indexes.rb +60 -0
  56. data/lib/neography/rest/relationship_indexes.rb +142 -0
  57. data/lib/neography/rest/relationship_properties.rb +52 -0
  58. data/lib/neography/rest/relationship_types.rb +11 -0
  59. data/lib/neography/rest/relationships.rb +16 -0
  60. data/lib/neography/rest/schema_indexes.rb +26 -0
  61. data/lib/neography/rest/spatial.rb +137 -0
  62. data/lib/neography/rest/transactions.rb +101 -0
  63. data/lib/neography/tasks.rb +207 -0
  64. data/lib/neography/version.rb +3 -0
  65. data/neography.gemspec +39 -0
  66. data/spec/integration/authorization_spec.rb +40 -0
  67. data/spec/integration/broken_spatial_spec.rb +28 -0
  68. data/spec/integration/index_spec.rb +71 -0
  69. data/spec/integration/neography_spec.rb +10 -0
  70. data/spec/integration/node_encoding_spec.rb +71 -0
  71. data/spec/integration/node_path_spec.rb +222 -0
  72. data/spec/integration/node_relationship_spec.rb +381 -0
  73. data/spec/integration/node_spec.rb +260 -0
  74. data/spec/integration/parsing_spec.rb +13 -0
  75. data/spec/integration/performance_spec.rb +17 -0
  76. data/spec/integration/relationship_spec.rb +37 -0
  77. data/spec/integration/rest_batch_no_streaming_spec.rb +41 -0
  78. data/spec/integration/rest_batch_spec.rb +604 -0
  79. data/spec/integration/rest_batch_streaming_spec.rb +51 -0
  80. data/spec/integration/rest_bulk_spec.rb +106 -0
  81. data/spec/integration/rest_constraints_spec.rb +72 -0
  82. data/spec/integration/rest_experimental_spec.rb +22 -0
  83. data/spec/integration/rest_gremlin_fail_spec.rb +46 -0
  84. data/spec/integration/rest_header_spec.rb +15 -0
  85. data/spec/integration/rest_index_spec.rb +481 -0
  86. data/spec/integration/rest_labels_spec.rb +128 -0
  87. data/spec/integration/rest_node_spec.rb +274 -0
  88. data/spec/integration/rest_other_node_relationship_spec.rb +137 -0
  89. data/spec/integration/rest_path_spec.rb +231 -0
  90. data/spec/integration/rest_plugin_spec.rb +177 -0
  91. data/spec/integration/rest_relationship_spec.rb +354 -0
  92. data/spec/integration/rest_relationship_types_spec.rb +18 -0
  93. data/spec/integration/rest_schema_index_spec.rb +32 -0
  94. data/spec/integration/rest_spatial_spec.rb +166 -0
  95. data/spec/integration/rest_transaction_spec.rb +166 -0
  96. data/spec/integration/rest_traverse_spec.rb +149 -0
  97. data/spec/integration/unmanaged_spec.rb +27 -0
  98. data/spec/matchers.rb +33 -0
  99. data/spec/neography_spec.rb +23 -0
  100. data/spec/spec_helper.rb +44 -0
  101. data/spec/unit/config_spec.rb +135 -0
  102. data/spec/unit/connection_spec.rb +284 -0
  103. data/spec/unit/node_spec.rb +100 -0
  104. data/spec/unit/properties_spec.rb +285 -0
  105. data/spec/unit/relationship_spec.rb +118 -0
  106. data/spec/unit/rest/batch_spec.rb +262 -0
  107. data/spec/unit/rest/clean_spec.rb +16 -0
  108. data/spec/unit/rest/constraints_spec.rb +45 -0
  109. data/spec/unit/rest/cypher_spec.rb +20 -0
  110. data/spec/unit/rest/extensions_spec.rb +28 -0
  111. data/spec/unit/rest/gremlin_spec.rb +25 -0
  112. data/spec/unit/rest/helpers_spec.rb +124 -0
  113. data/spec/unit/rest/labels_spec.rb +77 -0
  114. data/spec/unit/rest/node_auto_indexes_spec.rb +70 -0
  115. data/spec/unit/rest/node_indexes_spec.rb +140 -0
  116. data/spec/unit/rest/node_paths_spec.rb +77 -0
  117. data/spec/unit/rest/node_properties_spec.rb +79 -0
  118. data/spec/unit/rest/node_relationships_spec.rb +57 -0
  119. data/spec/unit/rest/node_traversal_spec.rb +35 -0
  120. data/spec/unit/rest/nodes_spec.rb +187 -0
  121. data/spec/unit/rest/relationship_auto_indexes_spec.rb +66 -0
  122. data/spec/unit/rest/relationship_indexes_spec.rb +132 -0
  123. data/spec/unit/rest/relationship_properties_spec.rb +79 -0
  124. data/spec/unit/rest/relationship_types_spec.rb +15 -0
  125. data/spec/unit/rest/relationships_spec.rb +21 -0
  126. data/spec/unit/rest/schema_index_spec.rb +30 -0
  127. data/spec/unit/rest/transactions_spec.rb +43 -0
  128. metadata +372 -0
@@ -0,0 +1,100 @@
1
+ module Neography
2
+ class PathTraverser
3
+ include Enumerable
4
+
5
+ attr_accessor :depth, :algorithm, :relationships, :get
6
+
7
+ def initialize(from, to, algorithm, all=false, types = nil, dir = "all" )
8
+ @from = from
9
+ @to = to
10
+ @algorithm = algorithm
11
+ @all = all
12
+ @relationships = Array.new
13
+ types.each do |type|
14
+ @relationships << {"type" => type.to_s, "direction" => dir.to_s }
15
+ end unless types.nil?
16
+ @get = ["node","rel"]
17
+ @loaded_nodes = Array.new
18
+ @loaded_rels = Array.new
19
+ end
20
+
21
+ def nodes
22
+ @get = ["node"]
23
+ self
24
+ end
25
+
26
+ def relationships
27
+ @get = ["rel"]
28
+ self
29
+ end
30
+
31
+ alias_method :rels, :relationships
32
+
33
+ def both(type)
34
+ @relationships << {"type" => type.to_s, "direction" => "all"}
35
+ self
36
+ end
37
+
38
+ def outgoing(type)
39
+ @relationships << {"type" => type.to_s, "direction" => "out"}
40
+ self
41
+ end
42
+
43
+ def incoming(type)
44
+ @relationships << {"type" => type.to_s, "direction" => "in"}
45
+ self
46
+ end
47
+
48
+ def depth(d)
49
+ d = 2147483647 if d == :all
50
+ @depth = d
51
+ self
52
+ end
53
+
54
+ def size
55
+ [*self].size
56
+ end
57
+
58
+ alias_method :length, :size
59
+
60
+ def each
61
+ iterator.each do |path|
62
+ paths = Array.new
63
+
64
+ if @get.include?("node")
65
+ path["nodes"].each_with_index do |n, i|
66
+ @loaded_nodes[get_id(n)] = Neography::Node.load(n) if @loaded_nodes.at(get_id(n)).nil?
67
+ paths[i * 2] = @loaded_nodes[get_id(n)]
68
+ end
69
+ end
70
+
71
+ if @get.include?("rel")
72
+ path["relationships"].each_with_index do |r, i|
73
+ @loaded_rels[get_id(r)] = Neography::Relationship.load(r) if @loaded_rels.at(get_id(r)).nil?
74
+ paths[i * 2 + 1] = @loaded_rels[get_id(r)]
75
+ end
76
+ end
77
+
78
+ yield paths.compact
79
+ end
80
+ end
81
+
82
+ def empty?
83
+ first == nil
84
+ end
85
+
86
+ def iterator
87
+ if @all.nil?
88
+ @from.neo_server.get_path(@from, @to, @relationships, @depth, @algorithm)
89
+ else
90
+ @from.neo_server.get_paths(@from, @to, @relationships, @depth, @algorithm)
91
+ end
92
+ end
93
+
94
+ private
95
+ def get_id(object)
96
+ object.split('/').last.to_i
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,110 @@
1
+ module Neography
2
+ module Property
3
+
4
+ def [](key)
5
+ @table[key.to_sym]
6
+ end
7
+
8
+ def []=(key, value)
9
+ key = key.to_sym
10
+ k_str = key.to_s
11
+ if value.nil?
12
+ unless @table[key].nil?
13
+ if node?
14
+ neo_server.remove_node_properties(self.neo_id, [k_str])
15
+ else
16
+ neo_server.remove_relationship_properties(self.neo_id, [k_str])
17
+ end
18
+ end
19
+ remove_ostruct_member(key)
20
+ else
21
+ if node?
22
+ neo_server.set_node_properties(self.neo_id, {k_str => value})
23
+ else
24
+ neo_server.set_relationship_properties(self.neo_id, {k_str => value})
25
+ end
26
+ new_ostruct_member(key, value)
27
+ end
28
+ end
29
+
30
+ # Set many properties at once and only issue one http
31
+ # request and update the node/relationship instance on the fly.
32
+ #
33
+ # To remove a property, set its value to nil.
34
+ def set_properties(hash)
35
+ hash.each do |key, value|
36
+ add_or_remove_ostruct_member(key, value)
37
+ end
38
+ rest_reset_properties
39
+ end
40
+
41
+ # As #set_properties, but this one hard resets the node's/relationship's
42
+ # properties to exactly what's given in the hash.
43
+ def reset_properties(hash)
44
+ @table.keys.each{|key| remove_ostruct_member(key)}
45
+ hash.each{|key,value| new_ostruct_member(key,value)}
46
+ rest_reset_properties
47
+ end
48
+
49
+ def add_or_remove_ostruct_member(name, value)
50
+ if value.nil?
51
+ remove_ostruct_member(name)
52
+ else
53
+ new_ostruct_member(name, value)
54
+ end
55
+ end
56
+
57
+ def new_ostruct_member(name, value)
58
+ name = name.to_sym
59
+ @table[name] = value
60
+ unless self.respond_to?(name)
61
+ meta = class << self; self; end
62
+ meta.send(:define_method, name) { @table[name] }
63
+ meta.send(:define_method, "#{name}=") do |new_value|
64
+ self[name.to_sym] = new_value
65
+ end
66
+ end
67
+ name
68
+ end
69
+
70
+ def remove_ostruct_member(name)
71
+ @table.delete(name.to_sym)
72
+ meta = class << self; self; end
73
+ names = [name, "#{name}="].map(&:to_sym)
74
+ names.each do |n|
75
+ meta.send(:remove_method, n) if self.respond_to?(n)
76
+ end
77
+ end
78
+
79
+ def method_missing(method_sym, *arguments, &block)
80
+ if (method_sym.to_s =~ /=$/) != nil
81
+ new_ostruct_member(method_sym.to_s.chomp("="), *arguments)
82
+
83
+ # We just defined the getter/setter above, but we haven't actually
84
+ # applied them yet.
85
+ self.send(method_sym, *arguments)
86
+ else
87
+ super
88
+ end
89
+ end
90
+
91
+ def attributes
92
+ @table.keys
93
+ end
94
+
95
+ def node?
96
+ self.is_a?(Neography::Node)
97
+ end
98
+
99
+ private
100
+
101
+ def rest_reset_properties
102
+ if node?
103
+ neo_server.reset_node_properties(self.neo_id, @table)
104
+ else
105
+ neo_server.reset_relationship_properties(self.neo_id, @table)
106
+ end
107
+ end
108
+
109
+ end
110
+ end
@@ -0,0 +1,28 @@
1
+ module Neography
2
+ class PropertyContainer < OpenStruct
3
+ attr_reader :neo_id
4
+
5
+ def initialize(hash=nil)
6
+ @table = {}
7
+ unless hash.nil?
8
+ if hash["self"] # coming from REST API
9
+ @neo_id = hash["self"].split('/').last
10
+ data = hash["data"]
11
+ elsif hash.is_a? Neography::Node # is already a Neography::Node
12
+ @neo_id = hash.neo_id
13
+ data = Hash[*hash.attributes.collect{|x| [x.to_sym, hash.send(x)]}.flatten]
14
+ elsif hash["data"] # coming from CYPHER
15
+ @neo_id = hash["data"].first.first["self"].split('/').last
16
+ data = hash["data"].first.first["data"]
17
+ end
18
+ else
19
+ data = []
20
+ end
21
+
22
+ for k,v in data
23
+ new_ostruct_member(k.to_sym, v)
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ require 'rails'
2
+
3
+ module Neography
4
+ class Railtie < Rails::Railtie
5
+
6
+ # To add an initialization step from your Railtie to Rails boot process, you just need to create an initializer block:
7
+ # See: http://api.rubyonrails.org/classes/Rails/Railtie.html
8
+ initializer 'neography.configure' do
9
+ # Provides a hook so people implementing the gem can do this in a railtie of their own:
10
+ # initializer "my_thing.neography_initialization", before: 'neography.configure' do
11
+ # require 'my_thing/neography'
12
+ # end
13
+ end
14
+
15
+ rake_tasks do
16
+ load 'neography/tasks.rb'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,78 @@
1
+ module Neography
2
+ class Relationship < PropertyContainer
3
+ include Neography::Equal
4
+ include Neography::Property
5
+ include Neography::Index
6
+
7
+ attr_accessor :start_node, :end_node, :rel_type
8
+
9
+ class << self
10
+
11
+ def create(type, from_node, to_node, props = nil)
12
+ rel = Neography::Relationship.new(from_node.neo_server.create_relationship(type, from_node, to_node, props))
13
+ rel.start_node = from_node
14
+ rel.end_node = to_node
15
+ rel.rel_type = type
16
+ rel
17
+ end
18
+
19
+ def create_unique(index, key, value, type, from_node, to_node, props = nil)
20
+ rel = Neography::Relationship.new(from_node.neo_server.create_unique_relationship(index, key, value, type, from_node, to_node, props))
21
+ rel.start_node = from_node
22
+ rel.end_node = to_node
23
+ rel.rel_type = type
24
+ rel
25
+ end
26
+
27
+ def load(rel, db = Neography::Rest.new)
28
+ raise ArgumentError.new("syntax deprecated") if rel.is_a?(Neography::Rest)
29
+
30
+ rel = db.get_relationship(rel)
31
+ if rel
32
+ rel = Neography::Relationship.new(rel, db)
33
+ rel.start_node = Neography::Node.load(rel.start_node, db)
34
+ rel.end_node = Neography::Node.load(rel.end_node, db)
35
+ end
36
+ rel
37
+ end
38
+ end
39
+
40
+ def initialize(hash=nil, server=nil)
41
+ super(hash)
42
+ @start_node = hash["start"].split('/').last
43
+ @end_node = hash["end"].split('/').last
44
+ @rel_type = hash["type"]
45
+ self.neo_server = server
46
+ end
47
+
48
+ def neo_server
49
+ @neo_server ||= self.start_node.neo_server
50
+ end
51
+
52
+ def neo_server=(server)
53
+ @neo_server = server
54
+ end
55
+
56
+ def del
57
+ start_node.neo_server.delete_relationship(neo_id)
58
+ end
59
+
60
+ def exist?
61
+ begin
62
+ start_node.neo_server.get_relationship(neo_id)
63
+ true
64
+ rescue Neography::RelationshipNotFoundException
65
+ false
66
+ end
67
+ end
68
+
69
+ def other_node(node)
70
+ if node == @start_node
71
+ @end_node
72
+ else
73
+ @start_node
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,80 @@
1
+ module Neography
2
+ class RelationshipTraverser
3
+ include Enumerable
4
+
5
+ def initialize(node, types, direction)
6
+ @node = node
7
+ @types = [types]
8
+ @direction = direction
9
+ end
10
+
11
+ def to_s
12
+ if @types.size == 1 && !@types.empty?
13
+ "#{self.class} [type: #{@type} dir:#{@direction}]"
14
+ elsif !@types.empty?
15
+ "#{self.class} [types: #{@types.join(',')} dir:#{@direction}]"
16
+ else
17
+ "#{self.class} [types: ANY dir:#{@direction}]"
18
+ end
19
+ end
20
+
21
+ def each
22
+ iterator.each do |i|
23
+ rel = Neography::Relationship.new(i, @node.neo_server)
24
+ rel.start_node = Neography::Node.load(rel.start_node, @node.neo_server)
25
+ rel.end_node = Neography::Node.load(rel.end_node, @node.neo_server)
26
+
27
+ yield rel if match_to_other?(rel)
28
+ end
29
+ end
30
+
31
+ def empty?
32
+ first == nil
33
+ end
34
+
35
+ def iterator
36
+ Array(@node.neo_server.get_node_relationships(@node, @direction, @types))
37
+ end
38
+
39
+ def match_to_other?(rel)
40
+ if @to_other.nil?
41
+ true
42
+ elsif @direction == :outgoing
43
+ rel.end_node == @to_other
44
+ elsif @direction == :incoming
45
+ rel.start_node == @to_other
46
+ else
47
+ rel.start_node == @to_other || rel.end_node == @to_other
48
+ end
49
+ end
50
+
51
+ def to_other(to_other)
52
+ @to_other = to_other
53
+ self
54
+ end
55
+
56
+ def del
57
+ each { |rel| @node.neo_server.delete_relationship(rel) }
58
+ end
59
+
60
+ def size
61
+ [*self].size
62
+ end
63
+
64
+ def both
65
+ @direction = :both
66
+ self
67
+ end
68
+
69
+ def incoming
70
+ @direction = :incoming
71
+ self
72
+ end
73
+
74
+ def outgoing
75
+ @direction = :outgoing
76
+ self
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,99 @@
1
+ require 'forwardable'
2
+
3
+ require 'neography/rest/helpers'
4
+ require 'neography/rest/schema_indexes'
5
+ require 'neography/rest/nodes'
6
+ require 'neography/rest/node_properties'
7
+ require 'neography/rest/node_relationships'
8
+ require 'neography/rest/other_node_relationships'
9
+ require 'neography/rest/node_indexes'
10
+ require 'neography/rest/node_auto_indexes'
11
+ require 'neography/rest/node_traversal'
12
+ require 'neography/rest/node_paths'
13
+ require 'neography/rest/node_labels'
14
+ require 'neography/rest/relationships'
15
+ require 'neography/rest/relationship_properties'
16
+ require 'neography/rest/relationship_indexes'
17
+ require 'neography/rest/relationship_auto_indexes'
18
+ require 'neography/rest/relationship_types'
19
+ require 'neography/rest/cypher'
20
+ require 'neography/rest/gremlin'
21
+ require 'neography/rest/extensions'
22
+ require 'neography/rest/batch'
23
+ require 'neography/rest/clean'
24
+ require 'neography/rest/transactions'
25
+ require 'neography/rest/spatial'
26
+ require 'neography/rest/constraints'
27
+ require 'neography/errors'
28
+ require 'neography/connection'
29
+
30
+ module Neography
31
+
32
+ class Rest
33
+ include Helpers
34
+ include RelationshipTypes
35
+ include NodeLabels
36
+ include SchemaIndexes
37
+ include Constraints
38
+ include Transactions
39
+ include Nodes
40
+ include NodeProperties
41
+ include Relationships
42
+ include RelationshipProperties
43
+ include NodeRelationships
44
+ include OtherNodeRelationships
45
+ include NodeIndexes
46
+ include NodeAutoIndexes
47
+ include RelationshipIndexes
48
+ include RelationshipAutoIndexes
49
+ include NodeTraversal
50
+ include NodePaths
51
+ include Cypher
52
+ include Gremlin
53
+ include Batch
54
+ include Extensions
55
+ include Spatial
56
+ include Clean
57
+ extend Forwardable
58
+
59
+ attr_reader :connection
60
+
61
+ def_delegators :@connection, :configuration
62
+
63
+ def initialize(options = ENV['NEO4J_URL'] || {})
64
+ @connection = Connection.new(options)
65
+ end
66
+
67
+ alias_method :list_indexes, :list_node_indexes
68
+ alias_method :add_to_index, :add_node_to_index
69
+ alias_method :remove_from_index, :remove_node_from_index
70
+ alias_method :get_index, :get_node_index
71
+
72
+ def delete_node!(id)
73
+ relationships = get_node_relationships(get_id(id))
74
+ relationships.each do |relationship|
75
+ delete_relationship(relationship["self"].split('/').last)
76
+ end unless relationships.nil?
77
+
78
+ delete_node(id)
79
+ end
80
+
81
+ # This is not yet implemented in the REST API
82
+ #
83
+ # def get_all_node
84
+ # puts "get all nodes"
85
+ # get("/nodes/")
86
+ # end
87
+
88
+ # relationships
89
+
90
+ def get_relationship_start_node(rel)
91
+ get_node(rel["start"])
92
+ end
93
+
94
+ def get_relationship_end_node(rel)
95
+ get_node(rel["end"])
96
+ end
97
+
98
+ end
99
+ end