neography-down 1.6.4

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.
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