neo4j-cypher 1.0.0.rc1 → 1.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -69,3 +69,33 @@ Matching relationships can be done with operators: <,>, -, and <=> or with the b
69
69
  end_nodes.as(:incoming),
70
70
  rel_types.as(:in_types)])
71
71
  end
72
+
73
+
74
+ === Co-Tagged Places - Places Related through Tags
75
+
76
+ Find places that are tagged with the same tags: Determine the tags for place x. What else is tagged the same as x that is not x."
77
+
78
+ "START place=node:node_auto_index(name = "CoffeeShop1") MATCH place-[:tagged]->tag<-[:tagged]-otherPlace RETURN otherPlace.name, collect(tag.name) ORDER By otherPlace.name desc"
79
+
80
+ Can be written like this:
81
+
82
+ Neo4j::Cypher.query do
83
+ other_place = node(:otherPlace)
84
+ place = lookup('node_auto_index', 'name', 'CoffeeShop1').as(:place)
85
+ place > rel(':tagged') > node(:tag) < rel(':tagged') < other_place
86
+ ret other_place[:name].desc, node(:tag)[:name].collect
87
+ end
88
+
89
+
90
+ Or in one line:
91
+
92
+ Neo4j::Cypher.query do
93
+ lookup('node_auto_index', 'name', 'CoffeeShop1') > rel(':tagged') > node(:tag).ret { |t| t[:name].collect } < rel(':tagged') < node(:otherPlace).ret { |n| n[:name].desc }
94
+ end
95
+
96
+
97
+ == License
98
+
99
+ The neo4j-cypher gem is released under the {MIT license}[www.opensource.org/licenses/MIT]
100
+
101
+
@@ -18,7 +18,7 @@ module Neo4j
18
18
  end
19
19
 
20
20
  def self.new_arg_from_clause(clause)
21
- Argument.new(clause.clause_list, clause.return_value, clause.as_alias? && clause.var_name)
21
+ Argument.new(clause.clause_list, clause.return_value, clause.as_alias? && clause.alias_name)
22
22
  end
23
23
 
24
24
  def self.new_arg_from_string(string, clause_list)
@@ -2,7 +2,7 @@ module Neo4j
2
2
  module Cypher
3
3
 
4
4
  class ClauseList
5
- attr_accessor :variables
5
+ attr_accessor :variables, :clause_list
6
6
  include Enumerable
7
7
 
8
8
  def initialize(variables = [])
@@ -16,6 +16,10 @@ module Neo4j
16
16
  end
17
17
 
18
18
  def include?(clause_type)
19
+ !!find(clause_type)
20
+ end
21
+
22
+ def find(clause_type)
19
23
  @clause_list.find { |c| c.clause_type == clause_type }
20
24
  end
21
25
 
@@ -146,21 +146,33 @@ module Neo4j
146
146
  end
147
147
 
148
148
  module Sortable
149
- def _sort_args(prop)
150
- return self if prop.nil?
151
- prop.is_a?(Symbol) ? Property.new(clause, prop).eval_context : prop
149
+ def _return_item
150
+ if self.is_a?(Neo4j::Cypher::ReturnItem::EvalContext)
151
+ self
152
+ else
153
+ @return_item ||= ReturnItem.new(clause_list, self).eval_context
154
+ end
152
155
  end
153
156
 
154
157
  def asc(*props)
155
- @return_item ||= ReturnItem.new(clause_list, self).eval_context
156
- @return_item.asc(_sort_args(props.first))
158
+ _return_item.asc(*props)
159
+ self
157
160
  end
158
161
 
159
162
  def desc(*props)
160
- @return_item ||= ReturnItem.new(clause_list, self).eval_context
161
- @return_item.desc(_sort_args(props.first))
163
+ _return_item.desc(*props)
164
+ self
162
165
  end
163
166
 
167
+ def skip(val)
168
+ _return_item.skip(val)
169
+ self
170
+ end
171
+
172
+ def limit(val)
173
+ _return_item.limit(val)
174
+ self
175
+ end
164
176
  end
165
177
 
166
178
  module ReturnOrder
@@ -253,15 +265,13 @@ module Neo4j
253
265
 
254
266
  module Variable
255
267
  def where(&block)
256
- x = block.call(self)
257
- clause_list.delete(x)
268
+ x = RootClause::EvalContext.new(self).instance_exec(self, &block)
258
269
  Operator.new(clause_list, x.clause, nil, "").unary!
259
270
  self
260
271
  end
261
272
 
262
273
  def where_not(&block)
263
- x = block.call(self)
264
- clause_list.delete(x)
274
+ x = RootClause::EvalContext.new(self).instance_exec(self, &block)
265
275
  Operator.new(clause_list, x.clause, nil, "not").unary!
266
276
  self
267
277
  end
@@ -301,6 +311,24 @@ module Neo4j
301
311
 
302
312
  module Matchable
303
313
 
314
+ ## Only in 1.9
315
+ if RUBY_VERSION > "1.9.0"
316
+ eval %{
317
+ def !=(other)
318
+ Operator.new(clause_list, clause, other, "<>").eval_context
319
+ end }
320
+ end
321
+
322
+ def ==(other)
323
+ Operator.new(clause_list, clause, other, "=").eval_context
324
+ end
325
+
326
+
327
+ def match(&cypher_dsl)
328
+ RootClause::EvalContext.new(self).instance_exec(self, &cypher_dsl)
329
+ self
330
+ end
331
+
304
332
  def with(*args, &cypher_dsl)
305
333
  With.new(clause_list, :where, self, *args, &cypher_dsl)
306
334
  self
@@ -18,10 +18,14 @@ module Neo4j
18
18
  end
19
19
 
20
20
  def as_alias(new_name)
21
- @alias = true
21
+ @alias = new_name
22
22
  self.var_name = new_name
23
23
  end
24
24
 
25
+ def alias_name
26
+ @alias
27
+ end
28
+
25
29
  def as_alias?
26
30
  !!@alias && var_name != return_value
27
31
  end
@@ -41,6 +41,7 @@ module Neo4j
41
41
  include Returnable
42
42
  include Aggregate
43
43
  include Alias
44
+ include Sortable
44
45
 
45
46
 
46
47
  def initialize(clause)
@@ -47,13 +47,18 @@ module Neo4j
47
47
  @post_fix = post_fix
48
48
  @valid = true
49
49
 
50
- # since we handle it our self in to_cypher method
51
- clause_list.delete(left_operand) if left_operand.kind_of?(Clause)
52
- clause_list.delete(right_operand) if right_operand.kind_of?(Clause)
50
+ # 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
53
 
54
54
  @neg = nil
55
55
  end
56
56
 
57
+ def declare_operand?(operand)
58
+ clause = operand.respond_to?(:clause) ? operand.clause : operand
59
+ clause.kind_of?(Clause) && clause.clause_type == :start
60
+ end
61
+
57
62
  def separator
58
63
  " and "
59
64
  end
@@ -16,15 +16,25 @@ module Neo4j
16
16
  def initialize(var, prop_name = nil)
17
17
  super(var.clause_list, :property, EvalContext)
18
18
  @var = var
19
- self.var_name = var.var_name
20
19
  @prop_name = prop_name
21
- @expr = prop_name ? "#{var.var_name}.#{prop_name}" : var.var_name.to_s
22
20
  end
23
21
 
22
+ def var_name
23
+ @var.var_name
24
+ end
25
+
26
+ def expr
27
+ if @function
28
+ "#{@prop_name}(#{var_name})"
29
+ else
30
+ @prop_name ? "#{@var.var_name}.#{@prop_name}" : @var.var_name.to_s
31
+ end
32
+ end
24
33
 
25
34
  # @private
26
35
  def to_function!(prop_name = nil)
27
- @expr = "#{prop_name || @prop_name}(#{var_name})"
36
+ @prop_name = prop_name if prop_name
37
+ @function = true
28
38
  eval_context
29
39
  end
30
40
 
@@ -44,7 +54,7 @@ module Neo4j
44
54
 
45
55
 
46
56
  def to_cypher
47
- @expr
57
+ expr
48
58
  end
49
59
 
50
60
  class EvalContext
@@ -74,6 +74,8 @@ module Neo4j
74
74
  include Returnable
75
75
  include Aggregate
76
76
  include Alias
77
+ include Sortable
78
+
77
79
 
78
80
  def rel_type
79
81
  Property.new(clause, 'type').to_function!
@@ -49,9 +49,9 @@ module Neo4j
49
49
  def to_cypher
50
50
  @orders.map do |pair|
51
51
  if pair[0] == :asc
52
- pair[1].map(&:return_value).join(', ')
52
+ pair[1].map{|p| p.alias_name || p.return_value}.join(', ')
53
53
  else
54
- pair[1].map(&:return_value).join(', ') + " DESC"
54
+ pair[1].map{|p| p.alias_name || p.return_value}.join(', ') + " DESC"
55
55
  end
56
56
  end.join(', ')
57
57
  end
@@ -85,13 +85,14 @@ module Neo4j
85
85
  class ReturnItem
86
86
  include Clause
87
87
  include Referenceable
88
+ attr_accessor :order_by
88
89
 
89
90
  def initialize(clause_list, name_or_ref)
90
91
  super(clause_list, :return_item, EvalContext)
91
92
  if name_or_ref.respond_to?(:clause)
92
93
  @delegated_clause = name_or_ref.clause
93
94
  @delegated_clause.referenced!
94
- as_alias(@delegated_clause.var_name) if @delegated_clause.as_alias?
95
+ as_alias(@delegated_clause.alias_name) if @delegated_clause.as_alias?
95
96
  else
96
97
  @return_value = name_or_ref.to_s
97
98
  end
@@ -102,7 +103,7 @@ module Neo4j
102
103
  end
103
104
 
104
105
  def return_value_with_alias
105
- as_alias? ? "#{return_value} as #{var_name}" : return_value
106
+ as_alias? ? "#{return_value} as #{alias_name}" : return_value
106
107
  end
107
108
 
108
109
  def return_value
@@ -33,8 +33,8 @@ module Neo4j
33
33
  end
34
34
 
35
35
  def return_names
36
- ret = clause_list.last
37
- ret.respond_to?(:return_items) ? ret.return_items.map { |ri| ri.var_name.to_sym } : []
36
+ ret = clause_list.clause_list.find{|r| r.respond_to?(:return_items)}
37
+ ret ? ret.return_items.map { |ri| (ri.alias_name || ri.return_value).to_sym } : []
38
38
  end
39
39
 
40
40
  class EvalContext
@@ -72,9 +72,14 @@ module Neo4j
72
72
 
73
73
  def initialize(clause_list, index_class, key, value)
74
74
  super(clause_list)
75
- index_type = index_class.index_type(key.to_s)
76
- raise "No index on #{index_class} property #{key}" unless index_type
77
- @index_name = index_class.index_name_for_type(index_type)
75
+ if index_class.respond_to?(:index_type)
76
+ index_type = index_class.index_type(key.to_s)
77
+ raise "No index on #{index_class} property #{key}" unless index_type
78
+ @index_name = index_class.index_name_for_type(index_type)
79
+ else
80
+ @index_name = index_class
81
+ end
82
+
78
83
  @query = %Q[#{key}="#{value}"]
79
84
  end
80
85
 
@@ -1,5 +1,5 @@
1
1
  module Neo4j
2
2
  module Cypher
3
- VERSION = '1.0.0.rc1'
3
+ VERSION = '1.0.0.rc2'
4
4
  end
5
5
  end
@@ -28,7 +28,7 @@ module Neo4j
28
28
  class EvalContext
29
29
  include Context
30
30
  include Alias
31
- include ReturnOrder
31
+ include Sortable
32
32
  include Aggregate
33
33
  include Comparable
34
34
  include Returnable
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neo4j-cypher
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc1
4
+ version: 1.0.0.rc2
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-20 00:00:00.000000000 Z
12
+ date: 2012-09-21 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! 'This gem is used in the JRuby neo4j gem but should work on any Ruby
15
15
  implementation since it simply