neo4j-cypher 1.0.0.rc2 → 1.0.0

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.
@@ -17,9 +17,7 @@ module Neo4j
17
17
 
18
18
 
19
19
  class Create
20
- include ToPropString
21
20
  include Clause
22
- include Referenceable
23
21
 
24
22
  def initialize(clause_list, props)
25
23
  super(clause_list, :create, EvalContext)
@@ -59,7 +57,6 @@ module Neo4j
59
57
 
60
58
  class CreatePath
61
59
  include Clause
62
- include Referenceable
63
60
 
64
61
  attr_reader :arg_list
65
62
 
@@ -0,0 +1,16 @@
1
+ module Neo4j
2
+ module Cypher
3
+ class Foreach < AbstractFilter
4
+
5
+ def initialize(clause_list, input_context, &block)
6
+ super(clause_list, :foreach, input_context)
7
+ # Input can either be a property array or a node/relationship collection
8
+ input = input_context.clause
9
+ clause_list.delete(input)
10
+ filter_initialize(input_context, '', " : ", &block)
11
+ end
12
+
13
+ end
14
+ end
15
+
16
+ end
@@ -3,7 +3,6 @@ module Neo4j
3
3
 
4
4
  class MatchStart
5
5
  include Clause
6
- include Referenceable
7
6
 
8
7
  attr_reader :match_list
9
8
  attr_accessor :algorithm
@@ -196,7 +195,7 @@ module Neo4j
196
195
  set_rel(rels.first)
197
196
  else
198
197
  # wrap and maybe join several relationship strings
199
- @rel_var = RelVar.join(clause_list, rels)
198
+ @rel_var = RelVar.new(clause_list, rels)
200
199
  end
201
200
  self
202
201
  end
@@ -215,16 +214,11 @@ module Neo4j
215
214
  elsif rel.respond_to?(:clause) && rel.clause.match_value
216
215
  @rel_var = rel.clause
217
216
  else
218
- @rel_var = RelVar.new(clause_list, rel)
217
+ @rel_var = RelVar.new(clause_list, [rel])
219
218
  end
220
219
  self
221
220
  end
222
221
 
223
- def self.new_first(match_start, from, rel)
224
- from_var = NodeVar.as_var(match_start.clause_list, from)
225
- RelLeftMatchContext.new(match_start, from_var).set_rel(rel)
226
- end
227
-
228
222
  def -(to)
229
223
  @match_start.match_list.delete(self) # since it is complete now
230
224
  RelRightMatchContext.new(@match_start, self, @rel_var, to, :both)
@@ -308,32 +302,41 @@ module Neo4j
308
302
  end
309
303
 
310
304
  def to_cypher_no_join
311
- "(#{@from.var_name})#{DIR_OPERATORS[@dir]}(#{@to.var_name})"
305
+ x = @to.match_value
306
+ "(#{@from.match_value})#{DIR_OPERATORS[@dir]}(#{x})"
312
307
  end
313
308
 
314
309
  def to_cypher_join
315
- "#{DIR_OPERATORS[@dir]}(#{@to.var_name})"
310
+ "#{DIR_OPERATORS[@dir]}(#{@to.match_value})"
316
311
  end
317
312
  end
318
313
 
319
314
  class Entities
320
315
  include Clause
316
+ attr_reader :input
321
317
 
322
318
  def initialize(clause_list, iterable, input)
323
319
  super(clause_list, :entities, EvalContext)
324
- eval_context.iterable = iterable
325
- eval_context.input = input.clause
320
+ @iterable = iterable
321
+ @input = input.clause
322
+ end
323
+
324
+ def referenced!
325
+ @input.referenced!
326
+ end
327
+
328
+ def return_value
329
+ "#{@iterable}(#{@input.var_name})"
326
330
  end
327
331
 
328
332
  class EvalContext
329
333
  include Context
330
334
  include PredicateMethods
331
- attr_accessor :input, :iterable
332
- #
333
- #def each(&cypher_dsl)
334
- # Predicate.new(clause_list, :clause => clause, :input => input, :predicate_block => cypher_dsl)
335
- # #RootClause::EvalContext.new(self).instance_exec(*arg_exec, &cypher_dsl)
336
- #end
335
+ include Returnable
336
+
337
+ include Variable
338
+ include Matchable
339
+ include Aggregate
337
340
  end
338
341
  end
339
342
 
@@ -0,0 +1,22 @@
1
+ module Neography
2
+
3
+ # Monkey patch so it works better with neo4-cypher gem and becomes more similar to neo4j-core
4
+ class Relationship
5
+ def _java_rel
6
+ self
7
+ end
8
+ end
9
+
10
+ class Node
11
+ def _java_node
12
+ self
13
+ end
14
+ end
15
+
16
+ class Rest
17
+ def execute_cypher(params, &dsl)
18
+ q = Neo4j::Cypher.query(params, &dsl).to_s
19
+ execute_query(q)
20
+ end
21
+ end
22
+ end
@@ -4,7 +4,6 @@ module Neo4j
4
4
  # Represents an unbound node variable used in match statements
5
5
  class NodeVar
6
6
  include Clause
7
- include Referenceable
8
7
 
9
8
  def initialize(clause_list, var_name = nil)
10
9
  super(clause_list, :node_var, EvalContext)
@@ -35,7 +35,6 @@ module Neo4j
35
35
  class Operator
36
36
  attr_reader :left_operand, :right_operand, :op, :neg, :eval_context
37
37
  include Clause
38
- include Referenceable
39
38
 
40
39
  def initialize(clause_list, left_operand, right_operand, op, clause_type = :where, post_fix = nil, &dsl)
41
40
  super(clause_list, clause_type, EvalContext)
@@ -48,19 +47,14 @@ module Neo4j
48
47
  @valid = true
49
48
 
50
49
  # since we handle it ourself in to_cypher method unless it needs to be declared (as a cypher start node/relationship)
51
- clause_list.delete(left_operand) unless declare_operand?(left_operand)
52
- clause_list.delete(right_operand) unless declare_operand?(right_operand)
53
-
50
+ clause_list.delete(left_operand) if remove_operand?(left_operand)
51
+ clause_list.delete(right_operand) if remove_operand?(right_operand)
54
52
  @neg = nil
55
53
  end
56
54
 
57
- def declare_operand?(operand)
55
+ def remove_operand?(operand)
58
56
  clause = operand.respond_to?(:clause) ? operand.clause : operand
59
- clause.kind_of?(Clause) && clause.clause_type == :start
60
- end
61
-
62
- def separator
63
- " and "
57
+ clause.kind_of?(Clause) && clause.clause_type == :where
64
58
  end
65
59
 
66
60
  def match_value
@@ -1,62 +1,11 @@
1
1
  module Neo4j
2
2
  module Cypher
3
- class Predicate
4
- include Clause
5
- include Referenceable
6
- attr_accessor :params
3
+ class Predicate < AbstractFilter
7
4
 
8
- def initialize(clause_list, params)
9
- super(clause_list, params[:clause])
10
- @identifier = :x
11
- @separator = params[:separator] || ','
12
- params[:input].referenced! if params[:input].respond_to?(:referenced!)
13
-
14
- clause_list.push
15
-
16
- var = NodeVar.as_var(clause_list, @identifier)
17
-
18
- input = params[:input]
19
-
20
- # TODO refactor please
21
- if input.kind_of?(Property)
22
- eval_prop = Property.new(var)
23
- eval_prop.expr = @identifier
24
- yield_param = eval_prop.eval_context
25
- args = ""
26
- else
27
- yield_param = var.eval_context
28
- args = "(#{input.var_name})"
29
- end
30
-
31
- result = RootClause::EvalContext.new(self).instance_exec(yield_param, &params[:predicate_block])
32
-
33
- result = case params[:clause]
34
- when :return_item
35
- block_result = result.clause.to_cypher
36
- "#{params[:op]}(#@identifier in #{params[:iterable]}#{args} : #{block_result})"
37
- when :foreach
38
- block_result = clause_list.to_cypher
39
- "#{params[:op]}(#@identifier in #{params[:iterable]}#{args} : #{block_result})"
40
- else
41
- block_result = clause_list.to_cypher
42
- "#{params[:op]}(#@identifier in #{params[:iterable]}#{args} WHERE #{block_result})"
43
- end
44
-
45
- clause_list.pop
46
- @result = result
47
- end
48
-
49
- def return_value
50
- to_cypher
51
- end
52
-
53
-
54
- def separator
55
- @separator
56
- end
57
-
58
- def to_cypher
59
- @result
5
+ def initialize(clause_list, method_name, input_context, &block)
6
+ super(clause_list, :where, input_context)
7
+ # Input can either be a property array or a node/relationship collection
8
+ filter_initialize(input_context, method_name, " WHERE ", &block)
60
9
  end
61
10
  end
62
11
 
@@ -10,15 +10,17 @@ module Neo4j
10
10
  # n=node(2, 3, 4); n[:name].collect
11
11
  # # same as START n0=node(2,3,4) RETURN collect(n0.property)
12
12
  class Property
13
- include Referenceable
14
13
  include Clause
15
14
 
15
+ attr_accessor :prop_name
16
+
16
17
  def initialize(var, prop_name = nil)
17
18
  super(var.clause_list, :property, EvalContext)
18
19
  @var = var
19
20
  @prop_name = prop_name
20
21
  end
21
22
 
23
+ # TODO check why needed
22
24
  def var_name
23
25
  @var.var_name
24
26
  end
@@ -65,6 +67,7 @@ module Neo4j
65
67
  include MathFunctions
66
68
  include PredicateMethods
67
69
  include Aggregate
70
+ include Returnable
68
71
 
69
72
  def asc
70
73
  ReturnItem.new(clause_list, self).eval_context.asc
@@ -88,17 +91,6 @@ module Neo4j
88
91
  self
89
92
  end
90
93
 
91
- # required by the Predicate Methods Module
92
- # @see PredicateMethods
93
- # @private
94
- def iterable
95
- clause.return_value
96
- end
97
-
98
- def input
99
- clause
100
- end
101
-
102
94
  # @private
103
95
  def in?(values)
104
96
  clause.unary_operator("", :where, " IN [#{values.map { |x| %Q["#{x}"] }.join(',')}]")
@@ -3,49 +3,43 @@ module Neo4j
3
3
 
4
4
  class RelVar
5
5
  include Clause
6
- include ToPropString
7
- include Referenceable
8
6
 
9
7
  def initialize(clause_list, expr, props = nil)
10
8
  super(clause_list, :rel_var, EvalContext)
11
9
 
12
- case expr
13
- when String
14
- @match_value = expr.empty? ? '?' : expr.to_s
15
- guess = expr.is_a?(String) && /([[:alpha:]_]*)/.match(expr)[1]
16
- self.var_name = guess.to_sym if guess && !guess.empty?
17
- when Symbol
18
- @match_value = ":`#{expr}`"
19
- else
20
- raise "Illegal arg for rel #{expr.class}"
21
- end
10
+ self.var_name = guess_var_name_from_string(expr.first) if expr.first.is_a?(String)
22
11
 
23
- @match_value = "#@match_value #{to_prop_string(props)}" if props
12
+ if props
13
+ @match_value = "#{match_value_from_args(expr)} #{to_prop_string(props)}"
14
+ else
15
+ @match_value = match_value_from_args(expr)
16
+ end
24
17
  end
25
18
 
26
- def rel_type
27
- @match_value.include?(':') ? @match_value.split(':').last : @match_value.sub('?', '')
19
+ def match_value_from_args(expr)
20
+ if expr.first.is_a?(String)
21
+ expr.first
22
+ elsif expr.first.is_a?(Symbol)
23
+ ":#{expr.map { |e| match_value_from_symbol(e) }.join('|')}"
24
+ elsif expr.empty?
25
+ '?'
26
+ else
27
+ # try to join several RelVars to one rel var
28
+ ":#{expr.map { |e| e.clause.rel_type }.join('|')}"
29
+ end
28
30
  end
29
31
 
30
- def self.join(clause_list, rel_types)
31
- rel_string = rel_types.map { |r| _rel_to_string(clause_list, r) }.join('|')
32
+ def guess_var_name_from_string(expr)
33
+ guess = /([[:alpha:]_]*)/.match(expr)[1]
34
+ guess && !guess.empty? && guess
35
+ end
32
36
 
33
- if rel_string.empty?
34
- RelVar.new(clause_list, "")
35
- else
36
- RelVar.new(clause_list, ":#{rel_string}")
37
- end
37
+ def match_value_from_symbol(expr)
38
+ "`#{expr}`"
38
39
  end
39
40
 
40
- def self._rel_to_string(clause_list, rel_or_symbol)
41
- case rel_or_symbol
42
- when String, Symbol
43
- RelVar.new(clause_list, rel_or_symbol).rel_type
44
- when Neo4j::Cypher::RelVar::EvalContext
45
- rel_or_symbol.clause.rel_type
46
- else
47
- raise "Unknown type of relationship, got #{rel_or_symbol.class}"
48
- end
41
+ def rel_type
42
+ @match_value.include?(':') ? @match_value.split(':').last : @match_value.sub('?', '')
49
43
  end
50
44
 
51
45
  def referenced!
@@ -84,7 +84,6 @@ module Neo4j
84
84
  # The return statement in the cypher query
85
85
  class ReturnItem
86
86
  include Clause
87
- include Referenceable
88
87
  attr_accessor :order_by
89
88
 
90
89
  def initialize(clause_list, name_or_ref)
@@ -33,7 +33,7 @@ module Neo4j
33
33
  end
34
34
 
35
35
  def return_names
36
- ret = clause_list.clause_list.find{|r| r.respond_to?(:return_items)}
36
+ ret = clause_list.return_clause
37
37
  ret ? ret.return_items.map { |ri| (ri.alias_name || ri.return_value).to_sym } : []
38
38
  end
39
39
 
@@ -46,12 +46,10 @@ module Neo4j
46
46
  # @return self
47
47
  def match(*, &match_dsl)
48
48
  instance_eval(&match_dsl) if match_dsl
49
- self
50
49
  end
51
50
 
52
51
  def match_not(&match_dsl)
53
52
  instance_eval(&match_dsl).not
54
- self
55
53
  end
56
54
 
57
55
  # Does nothing, just for making the DSL easier to read (maybe)
@@ -60,29 +58,55 @@ module Neo4j
60
58
  self
61
59
  end
62
60
 
63
- def where(w=nil)
64
- Where.new(clause_list, w) if w.is_a?(String)
61
+ def where(w=nil, &block)
62
+ Where.new(clause_list, self, w, &block)
63
+ self
64
+ end
65
+
66
+ def where_not(w=nil, &block)
67
+ Where.new(clause_list, self, w, &block).neg!
65
68
  self
66
69
  end
67
70
 
68
71
  # Specifies a start node by performing a lucene query.
69
- # @param [Class] index_class a class responsible for an index
72
+ # @param [Class, String] index_class a class responsible for an index or the string value of the index
70
73
  # @param [String] q the lucene query
71
74
  # @param [Symbol] index_type the type of index
72
- # @return [NodeQuery]
75
+ # @return [LuceneQuery]
73
76
  def query(index_class, q, index_type = :exact)
74
- NodeQuery.new(clause_list, index_class, q, index_type).eval_context
77
+ LuceneQuery.query_node_by_class(clause_list, index_class, q, index_type).eval_context
78
+ end
79
+
80
+ # Specifies a start relationship by performing a lucene query.
81
+ # @param [Class, String] index_class a class responsible for an index or the string value of the index
82
+ # @param [String] q the lucene query
83
+ # @param [Symbol] index_type the type of index
84
+ # @return [LuceneQuery]
85
+ def query_rel(index_class, q, index_type = :exact)
86
+ LuceneQuery.query_rel_by_class(clause_list, index_class, q, index_type).eval_context
75
87
  end
76
88
 
89
+
77
90
  # Specifies a start node by performing a lucene query.
78
- # @param [Class] index_class a class responsible for an index
91
+ # @param [Class, String] index_class a class responsible for an index or the string value of the index
79
92
  # @param [String, Symbol] key the key we ask for
80
93
  # @param [String, Symbol] value the value of the key we ask for
81
- # @return [NodeLookup]
94
+ # @return [LuceneQuery]
82
95
  def lookup(index_class, key, value)
83
- NodeLookup.new(clause_list, index_class, key, value).eval_context
96
+ LuceneQuery.lookup_node_by_class(clause_list, index_class, key, value).eval_context
84
97
  end
85
98
 
99
+
100
+ # Specifies a start relationship by performing a lucene query.
101
+ # @param [Class, String] index_class a class responsible for an index or the string value of the index
102
+ # @param [String, Symbol] key the key we ask for
103
+ # @param [String, Symbol] value the value of the key we ask for
104
+ # @return [LuceneQuery]
105
+ def lookup_rel(index_class, key, value)
106
+ LuceneQuery.lookup_rel_by_class(clause_list, index_class, key, value).eval_context
107
+ end
108
+
109
+
86
110
  # Creates a node variable.
87
111
  # It will create different variables depending on the type of the first element in the nodes argument.
88
112
  # * Fixnum - it will be be used as neo_id for start node(s) (StartNode)
@@ -106,14 +130,9 @@ module Neo4j
106
130
  def rel(*rels)
107
131
  if rels.first.is_a?(Fixnum) || rels.first.respond_to?(:neo_id)
108
132
  StartRel.new(clause_list, rels).eval_context
109
- elsif rels.first.is_a?(Symbol)
110
- RelVar.new(clause_list, ":`#{rels.first}`", rels[1]).eval_context
111
- elsif rels.first.is_a?(String)
112
- RelVar.new(clause_list, rels.first, rels[1]).eval_context
113
- elsif rels.empty?
114
- RelVar.new(clause_list, '?').eval_context
115
133
  else
116
- raise "Unknown arg #{rels.inspect}"
134
+ props = rels.pop if rels.last.is_a?(Hash)
135
+ RelVar.new(clause_list, rels, props).eval_context
117
136
  end
118
137
  end
119
138
 
@@ -145,13 +164,16 @@ module Neo4j
145
164
  end
146
165
 
147
166
  def nodes(*args)
148
- s = args.map { |x| x.clause.referenced!; x.clause.var_name }.join(", ")
149
- ReturnItem.new(clause_list, "nodes(#{s})").eval_context
167
+ _entities(args, 'nodes')
150
168
  end
151
169
 
152
170
  def rels(*args)
153
- s = args.map { |x| x.clause.referenced!; x.clause.var_name }.join(", ")
154
- ReturnItem.new(clause_list, "relationships(#{s})").eval_context
171
+ _entities(args, 'relationships')
172
+ end
173
+
174
+ def _entities(arg_list, entity_type)
175
+ s = arg_list.map { |x| x.clause.referenced!; x.clause.var_name }.join(", ")
176
+ ReturnItem.new(clause_list, "#{entity_type}(#{s})").eval_context
155
177
  end
156
178
 
157
179
  def create_path(*args, &block)