Class: Neo4j::Server::CypherSession

Inherits:
Neo4j::Session show all
Includes:
Core::CypherTranslator, Resource
Defined in:
lib/neo4j-server/cypher_session.rb

Constant Summary

Constants included from Core::CypherTranslator

Core::CypherTranslator::SANITIZE_ESCAPED_REGEXP

Instance Attribute Summary collapse

Attributes included from Resource

#resource_data, #resource_url

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Core::CypherTranslator

#cypher_prop_list, #escape_quotes, #escape_value, #sanitize_escape_sequences, sanitized_column_names, translate_response

Methods included from Resource

#convert_from_json_value, #expect_response_code, #handle_response_error, #init_resource_data, #resource_headers, #resource_url_id, #response_exception, #wrap_resource

Methods inherited from Neo4j::Session

_listeners, _notify_listeners, add_listener, #auto_commit?, create_session, current, current!, inspect, named, on_session_available, open_named, query, register, register_db, #running, set_current, #shutdown, #start, unregister

Constructor Details

#initialize(data_url, connection) ⇒ CypherSession

Returns a new instance of CypherSession.



51
52
53
54
55
56
# File 'lib/neo4j-server/cypher_session.rb', line 51

def initialize(data_url, connection)
  @connection = connection
  Neo4j::Session.register(self)
  initialize_resource(data_url)
  Neo4j::Session._notify_listeners(:session_available, self)
end

Instance Attribute Details

#connectionObject (readonly)

Returns the value of attribute connection.



13
14
15
# File 'lib/neo4j-server/cypher_session.rb', line 13

def connection
  @connection
end

Class Method Details

.create_connection(params) ⇒ Faraday

Parameters:

  • params (Hash)

    could be empty or contain basic authentication user and password

Returns:

  • (Faraday)

See Also:



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/neo4j-server/cypher_session.rb', line 18

def self.create_connection(params)
  init_params = params[:initialize] and params.delete(:initialize)
  conn = Faraday.new(init_params) do |b|
    b.request :basic_auth, params[:basic_auth][:username], params[:basic_auth][:password] if params[:basic_auth]
    b.request :json
    #b.response :logger
    b.response :json, :content_type => "application/json"
    #b.use Faraday::Response::RaiseError
    b.use Faraday::Adapter::NetHttpPersistent
    # b.adapter  Faraday.default_adapter
  end
  conn.headers = {'Content-Type' => 'application/json'}
  conn
end

.open(endpoint_url = nil, params = {}) ⇒ Object

Opens a session to the database

Parameters:

  • endpoint_url (String) (defaults to: nil)
  • params (Hash) (defaults to: {})

    faraday params, see #create_connection or an already created faraday connection

See Also:

  • Neo4j::Session#open


38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/neo4j-server/cypher_session.rb', line 38

def self.open(endpoint_url=nil, params = {})
  connection = params[:connection] || create_connection(params)
  url = endpoint_url || 'http://localhost:7474'
  response = connection.get(url)
  raise "Server not available on #{url} (response code #{response.status})" unless response.status == 200

  root_data = response.body
  data_url = root_data['data']
  data_url << '/' unless data_url.end_with?('/')

  CypherSession.new(data_url, connection)
end

Instance Method Details

#_query(q, params = nil) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
# File 'lib/neo4j-server/cypher_session.rb', line 206

def _query(q, params=nil)
  curr_tx = Neo4j::Transaction.current
  if (curr_tx)
    curr_tx._query(q, params)
  else
    url = resource_url('cypher')
    q = params.nil? ? { 'query' => q } : { 'query' => q, 'params' => params}
    response = @connection.post(url, q)
    CypherResponse.create_with_no_tx(response)
  end
end

#_query_data(q) ⇒ Object



188
189
190
191
192
# File 'lib/neo4j-server/cypher_session.rb', line 188

def _query_data(q)
  r = _query_or_fail(q, true)
  # the response is different if we have a transaction or not
  Neo4j::Transaction.current ? r : r['data']
end

#_query_entity_data(q, id = nil) ⇒ Object



200
201
202
203
204
# File 'lib/neo4j-server/cypher_session.rb', line 200

def _query_entity_data(q, id=nil)
  response = _query(q)
  response.raise_error if response.error?
  response.entity_data(id)
end

#_query_or_fail(q, single_row = false, params = nil) ⇒ Object



194
195
196
197
198
# File 'lib/neo4j-server/cypher_session.rb', line 194

def _query_or_fail(q, single_row = false, params=nil)
  response = _query(q, params)
  response.raise_error if response.error?
  single_row ? response.first_data : response
end

#begin_txObject



88
89
90
91
92
93
94
95
96
# File 'lib/neo4j-server/cypher_session.rb', line 88

def begin_tx
  if Neo4j::Transaction.current
    # Handle nested transaction "placebo transaction"
    Neo4j::Transaction.current.push_nested!
  else
    wrap_resource(self, 'transaction', CypherTransaction, :post, @connection)
  end
  Neo4j::Transaction.current
end

#closeObject



83
84
85
86
# File 'lib/neo4j-server/cypher_session.rb', line 83

def close
  super
  Neo4j::Transaction.unregister_current
end

#create_label(name) ⇒ Object



128
129
130
# File 'lib/neo4j-server/cypher_session.rb', line 128

def create_label(name)
  CypherLabel.new(self, name)
end

#create_node(props = nil, labels = []) ⇒ Object



98
99
100
101
102
103
# File 'lib/neo4j-server/cypher_session.rb', line 98

def create_node(props=nil, labels=[])
  l = labels.empty? ? "" : ":" + labels.map{|k| "`#{k}`"}.join(':')
  q = "CREATE (n#{l} #{cypher_prop_list(props)}) RETURN ID(n)"
  cypher_response = _query_or_fail(q, true)
  CypherNode.new(self, cypher_response)
end

#db_typeObject



58
59
60
# File 'lib/neo4j-server/cypher_session.rb', line 58

def db_type
  :server_db
end

#find_all_nodes(label_name) ⇒ Object



160
161
162
163
# File 'lib/neo4j-server/cypher_session.rb', line 160

def find_all_nodes(label_name)
  response = _query_or_fail("MATCH (n:`#{label_name}`) RETURN ID(n)")
  search_result_to_enumerable_first_column(response)
end

#find_nodes(label_name, key, value) ⇒ Object



165
166
167
168
169
170
171
172
173
174
# File 'lib/neo4j-server/cypher_session.rb', line 165

def find_nodes(label_name, key, value)
  value = "'#{value}'" if value.is_a? String
  
  response = _query_or_fail <<-CYPHER
    MATCH (n:`#{label_name}`)
    WHERE n.#{key} = #{value}
    RETURN ID(n)
  CYPHER
  search_result_to_enumerable_first_column(response)
end

#indexes(label) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/neo4j-server/cypher_session.rb', line 146

def indexes(label)
  response = @connection.get("#{@resource_url}schema/index/#{label}")
  expect_response_code(response, 200)
  data_resource = response.body

  property_keys = data_resource.map do |row|
    row['property_keys'].map(&:to_sym)
  end

  {
      property_keys: property_keys
  }
end

#initialize_resource(data_url) ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/neo4j-server/cypher_session.rb', line 74

def initialize_resource(data_url)
  response = @connection.get(data_url)
  expect_response_code(response,200)
  data_resource = response.body
  raise "No data_resource for #{response.body}" unless data_resource
  # store the resource data
  init_resource_data(data_resource, data_url)
end

#inspectObject



66
67
68
# File 'lib/neo4j-server/cypher_session.rb', line 66

def inspect
  "#{to_s} version: '#{version}'"
end

#load_node(neo_id) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
# File 'lib/neo4j-server/cypher_session.rb', line 105

def load_node(neo_id)
  cypher_response = _query("START n=node(#{neo_id}) RETURN n")
  if (!cypher_response.error?)
    result = cypher_response.entity_data(neo_id)
    CypherNode.new(self, result)
  elsif (cypher_response.error_status =~ /EntityNotFound/)
    return nil
  else
    cypher_response.raise_error
  end
end

#load_relationship(neo_id) ⇒ Object



117
118
119
120
121
122
123
124
125
126
# File 'lib/neo4j-server/cypher_session.rb', line 117

def load_relationship(neo_id)
  cypher_response = _query("START r=relationship(#{neo_id}) RETURN TYPE(r)")
  if (!cypher_response.error?)
    CypherRelationship.new(self, neo_id, cypher_response.first_data)
  elsif (cypher_response.error_msg =~ /not found/)  # Ugly that the Neo4j API gives us this error message
    return nil
  else
    cypher_response.raise_error
  end
end

#map_column(key, map, data) ⇒ Object



245
246
247
248
249
250
251
252
253
254
# File 'lib/neo4j-server/cypher_session.rb', line 245

def map_column(key, map, data)
  case map[key]
    when :node
      CypherNode.new(self, data).wrapper
    when :rel, :relationship
      CypherRelationship.new(self, data)
    else
      data
  end
end

#query(*args) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
# File 'lib/neo4j-server/cypher_session.rb', line 176

def query(*args)
  if [[String], [String, Hash]].include?(args.map(&:class))
    query, params = args[0,2]
    response = _query(query, params)
    response.raise_error if response.error?
    response.to_node_enumeration(query)
  else
    options = args[0] || {}
    Neo4j::Core::Query.new(options.merge(session: self))
  end
end

#search_result_to_enumerable(response, ret, map) ⇒ Object



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/neo4j-server/cypher_session.rb', line 257

def search_result_to_enumerable(response, ret, map)
  return [] unless response.data

  if (ret.size == 1)
    Enumerator.new do |yielder|
      response.data.each do |data|
        yielder << map_column(key, map, data[0])
      end
    end

  else
    Enumerator.new do |yielder|
      response.data.each do |data|
        hash = {}
        ret.each_with_index do |key, i|
          hash[key] = map_column(key, map, data[i])
        end
        yielder << hash
      end
    end
  end
end

#search_result_to_enumerable_first_column(response) ⇒ Object



218
219
220
221
222
223
224
225
# File 'lib/neo4j-server/cypher_session.rb', line 218

def search_result_to_enumerable_first_column(response)
  return [] unless response.data
  if Neo4j::Transaction.current
    search_result_to_enumerable_first_column_with_tx(response)
  else
    search_result_to_enumerable_first_column_without_tx(response)
  end
end

#search_result_to_enumerable_first_column_with_tx(response) ⇒ Object



227
228
229
230
231
232
233
234
235
# File 'lib/neo4j-server/cypher_session.rb', line 227

def search_result_to_enumerable_first_column_with_tx(response)
  Enumerator.new do |yielder|
    response.data.each do |data|
      data["row"].each do |id|
        yielder << CypherNode.new(self, id).wrapper
      end
    end
  end
end

#search_result_to_enumerable_first_column_without_tx(response) ⇒ Object



237
238
239
240
241
242
243
# File 'lib/neo4j-server/cypher_session.rb', line 237

def search_result_to_enumerable_first_column_without_tx(response)
    Enumerator.new do |yielder|
      response.data.each do |data|
        yielder << CypherNode.new(self, data[0]).wrapper
      end
    end
end

#super_queryObject



12
# File 'lib/neo4j-server/cypher_session.rb', line 12

alias_method :super_query, :query

#to_sObject



62
63
64
# File 'lib/neo4j-server/cypher_session.rb', line 62

def to_s
  "#{self.class} url: '#{@resource_url}'"
end

#uniqueness_constraints(label) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/neo4j-server/cypher_session.rb', line 132

def uniqueness_constraints(label)
  response = @connection.get("#{@resource_url}schema/constraint/#{label}/uniqueness")
  expect_response_code(response, 200)
  data_resource = response.body

  property_keys = data_resource.map do |row|
    row['property_keys'].map(&:to_sym)
  end

  {
      property_keys: property_keys
  }
end

#versionObject



70
71
72
# File 'lib/neo4j-server/cypher_session.rb', line 70

def version
  resource_data ? resource_data['neo4j_version'] : ''
end