ashikawa-core 0.1 → 0.2
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.
- data/Guardfile +18 -0
- data/README.md +10 -10
- data/Rakefile +5 -4
- data/ashikawa-core.gemspec +14 -6
- data/lib/ashikawa-core.rb +1 -0
- data/lib/ashikawa-core/collection.rb +189 -98
- data/lib/ashikawa-core/connection.rb +18 -20
- data/lib/ashikawa-core/cursor.rb +65 -0
- data/lib/ashikawa-core/database.rb +33 -46
- data/lib/ashikawa-core/document.rb +63 -22
- data/lib/ashikawa-core/exceptions/document_not_found.rb +8 -0
- data/lib/ashikawa-core/index.rb +47 -0
- data/lib/ashikawa-core/version.rb +1 -1
- data/spec/fixtures/cursor/26011191-2.json +19 -0
- data/spec/fixtures/cursor/26011191-3.json +13 -0
- data/spec/fixtures/cursor/26011191.json +19 -0
- data/spec/fixtures/cursor/query.json +18 -0
- data/spec/fixtures/documents/new-4590-333.json +5 -0
- data/spec/fixtures/indices/all.json +22 -0
- data/spec/fixtures/indices/hash-index.json +12 -0
- data/spec/fixtures/indices/new-hash-index.json +12 -0
- data/spec/fixtures/simple-queries/all.json +10 -4
- data/spec/fixtures/simple-queries/all_limit.json +9 -3
- data/spec/fixtures/simple-queries/all_skip.json +9 -3
- data/spec/fixtures/simple-queries/example.json +9 -3
- data/spec/fixtures/simple-queries/near.json +11 -5
- data/spec/fixtures/simple-queries/range.json +10 -0
- data/spec/fixtures/simple-queries/within.json +9 -3
- data/spec/integration/arango_helper.rb +27 -0
- data/spec/integration/basic_spec.rb +107 -28
- data/spec/integration/spec_helper.rb +0 -28
- data/spec/unit/collection_spec.rb +190 -83
- data/spec/unit/connection_spec.rb +17 -17
- data/spec/unit/cursor_spec.rb +75 -0
- data/spec/unit/database_spec.rb +34 -19
- data/spec/unit/document_spec.rb +77 -6
- data/spec/unit/index_spec.rb +39 -0
- metadata +98 -6
data/Guardfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
guard 'bundler' do
|
2
|
+
watch(/^.+\.gemspec/)
|
3
|
+
end
|
4
|
+
|
5
|
+
guard 'yard' do
|
6
|
+
watch(%r{lib/.+\.rb})
|
7
|
+
end
|
8
|
+
|
9
|
+
guard 'rspec', :version => 2, :spec_paths => "spec/unit" do
|
10
|
+
watch(%r{lib/.+\.rb})
|
11
|
+
watch(%r{spec/.+\.rb})
|
12
|
+
end
|
13
|
+
|
14
|
+
guard 'rspec', :version => 2, :spec_paths => "spec/integration" do
|
15
|
+
watch(%r{lib/.+\.rb})
|
16
|
+
watch(%r{spec/.+\.rb})
|
17
|
+
end
|
18
|
+
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Ashikawa Core
|
2
2
|
|
3
3
|
[](http://travis-ci.org/triAGENS/ashikawa-core)
|
4
|
+
[](https://codeclimate.com/github/triAGENS/ashikawa-core)
|
4
5
|
|
5
6
|
Ashikawa Core is a Wrapper around the ArangoDB Rest API. It provides low level access and will be used in different ArangoDB ODMs.
|
6
7
|
|
@@ -39,6 +40,14 @@ Now you can run `rake` to see all tests passing (hopefully). Happy coding!
|
|
39
40
|
|
40
41
|
You can also start up yard for documentation: `rake yard:server`
|
41
42
|
|
43
|
+
### Guard
|
44
|
+
|
45
|
+
Guard is a tool for comfortable development. If you want to use it for development, you have to first start an instance of ArangoDB and then start guard with `guard`. This will:
|
46
|
+
|
47
|
+
* Run a documentation server on `http://localhost:8808`
|
48
|
+
* Run `bundle` whenever you change the dependencies
|
49
|
+
* Run the integration and unit tests whenever you change a file in the lib or spec directory
|
50
|
+
|
42
51
|
### Continuous Integration
|
43
52
|
|
44
53
|
Our tests are run on Travis CI, the build status is displayed above. **Please note** that it only runs the unit tests and not the integration tests, because that would require ArangoDB to be installed on the Travis CI boxes. *Therefore green doesn't neccessarily mean green* (which is unfortunate).
|
@@ -50,14 +59,5 @@ When you want to write code for the project, please follow these guidelines:
|
|
50
59
|
1. Claim the ticket: Tell us that you want to work on a certain ticket, we will assign it to you (We don't want two people to work on the same thing ;) )
|
51
60
|
2. Write an Integration Test: Describe what you want to do (our integration tests touch the database)
|
52
61
|
3. Implement it: Write a unit test, check that it fails, make the test pass – repeat (our unit tests don't touch the database)
|
53
|
-
4. Write Documentation for it
|
62
|
+
4. Write Documentation for it.
|
54
63
|
5. Check with `rake` that everything is fine and send the Pull Request :)
|
55
|
-
|
56
|
-
## Documentation
|
57
|
-
|
58
|
-
We want `Ashikawa::Core` to be a solid foundation for all Ruby Libraries connecting to ArangoDB. Therefore we want an excellent documentation. We created two rake tasks:
|
59
|
-
|
60
|
-
* `rake yard:report`: Measure docs in lib/**/*.rb with yardstick
|
61
|
-
* `rake yard:verify`: Verify that yardstick coverage is 100%
|
62
|
-
|
63
|
-
The Yardstick coverage will be checked by our CI. Please make sure that the coverage is always at 100%.
|
data/Rakefile
CHANGED
@@ -9,6 +9,7 @@ require "rspec/core/rake_task"
|
|
9
9
|
namespace :spec do
|
10
10
|
desc "Run the integration tests. Requires ArangoDB."
|
11
11
|
RSpec::Core::RakeTask.new(:integration) do |spec|
|
12
|
+
spec.rspec_opts = "--require integration/arango_helper.rb"
|
12
13
|
spec.pattern = "spec/integration/*_spec.rb"
|
13
14
|
end
|
14
15
|
|
@@ -58,9 +59,9 @@ namespace :yard do
|
|
58
59
|
end
|
59
60
|
|
60
61
|
desc "Run Unit Tests and verify documentation - no ArangoDB required"
|
61
|
-
# task :ci => ["spec:unit", "yard:verify"
|
62
|
-
task :ci => ["spec:unit"
|
62
|
+
# task :ci => ["spec:unit", "yard:verify"]
|
63
|
+
task :ci => ["spec:unit"]
|
63
64
|
|
64
65
|
desc "Run all tests and verify documentation - ArangoDB required"
|
65
|
-
# task :default => ["spec:all", "yard:verify"
|
66
|
-
task :default => ["spec:all"
|
66
|
+
# task :default => ["spec:all", "yard:verify"]
|
67
|
+
task :default => ["spec:all"]
|
data/ashikawa-core.gemspec
CHANGED
@@ -7,13 +7,13 @@ Gem::Specification.new do |gem|
|
|
7
7
|
gem.version = Ashikawa::Core::VERSION
|
8
8
|
gem.authors = ["moonglum", "EinLama"]
|
9
9
|
gem.email = ["me@moonglum.net", "tobias.eilert@me.com"]
|
10
|
-
gem.homepage = ""
|
10
|
+
gem.homepage = "https://github.com/triAGENS/ashikawa-core"
|
11
11
|
gem.summary = "Ashikawa Core is a Wrapper around the ArangoDB Rest API"
|
12
12
|
gem.description = "Ashikawa Core is a Wrapper around the ArangoDB Rest API. It provides low level access and will be used in different ArangoDB ODMs."
|
13
|
-
|
13
|
+
|
14
14
|
gem.required_ruby_version = '>= 1.9.2'
|
15
15
|
gem.requirements << "ArangoDB"
|
16
|
-
|
16
|
+
|
17
17
|
gem.rubyforge_project = "ashikawa-core"
|
18
18
|
|
19
19
|
gem.files = `git ls-files`.split("\n")
|
@@ -23,18 +23,26 @@ Gem::Specification.new do |gem|
|
|
23
23
|
|
24
24
|
# Runtime Dependencies
|
25
25
|
gem.add_dependency "rest-client", "~> 1.6.7"
|
26
|
-
|
26
|
+
|
27
27
|
# Runtime Dependencies (JRuby only)
|
28
28
|
if defined? PLATFORM and PLATFORM == 'java'
|
29
29
|
gem.add_dependency "json", "~> 1.6.6"
|
30
30
|
gem.add_dependency "jruby-openssl", "~> 0.7.6.1"
|
31
|
+
else
|
32
|
+
# RedCarpet is not compatible with JRuby
|
33
|
+
# It is only needed to generate the YARD Documentation
|
34
|
+
gem.add_development_dependency "redcarpet", "~> 2.1.1"
|
31
35
|
end
|
32
|
-
|
36
|
+
|
33
37
|
# Development Dependencies
|
34
38
|
gem.add_development_dependency "rake", "~> 0.9.2.2"
|
35
39
|
gem.add_development_dependency "rspec", "~> 2.11.0"
|
36
40
|
gem.add_development_dependency "yard", "~> 0.8.2.1"
|
37
41
|
gem.add_development_dependency "webmock", "~> 1.8.9"
|
38
42
|
# gem.add_development_dependency "yardstick", "~> 0.6.0"
|
39
|
-
|
43
|
+
|
44
|
+
gem.add_development_dependency "guard", "~> 1.3.2"
|
45
|
+
gem.add_development_dependency "guard-rspec", "~> 1.2.1"
|
46
|
+
gem.add_development_dependency "guard-bundler", "~> 1.0.0"
|
47
|
+
gem.add_development_dependency "guard-yard", "~> 2.0.0"
|
40
48
|
end
|
data/lib/ashikawa-core.rb
CHANGED
@@ -3,6 +3,7 @@ require "ashikawa-core/connection"
|
|
3
3
|
require "ashikawa-core/database"
|
4
4
|
require "ashikawa-core/document"
|
5
5
|
require "ashikawa-core/version"
|
6
|
+
require "ashikawa-core/exceptions/document_not_found"
|
6
7
|
|
7
8
|
# Ashikawa is a project dedicated to connect Ruby and ArangoDB
|
8
9
|
module Ashikawa
|
@@ -1,11 +1,16 @@
|
|
1
1
|
require "ashikawa-core/document"
|
2
|
+
require "ashikawa-core/index"
|
3
|
+
require "ashikawa-core/cursor"
|
4
|
+
require "forwardable"
|
2
5
|
|
3
6
|
module Ashikawa
|
4
7
|
module Core
|
5
8
|
# Represents a certain Collection within the Database
|
6
9
|
class Collection
|
10
|
+
extend Forwardable
|
11
|
+
|
7
12
|
# The name of the collection, must be unique
|
8
|
-
#
|
13
|
+
#
|
9
14
|
# @return [String]
|
10
15
|
# @api public
|
11
16
|
# @example Change the name of a collection
|
@@ -23,9 +28,9 @@ module Ashikawa
|
|
23
28
|
# collection.name = "example_2"
|
24
29
|
# collection.name # => "example_2"
|
25
30
|
attr_reader :name
|
26
|
-
|
31
|
+
|
27
32
|
# The ID of the collection. Is set by the database and unique
|
28
|
-
#
|
33
|
+
#
|
29
34
|
# @return [Fixnum]
|
30
35
|
# @api public
|
31
36
|
# @example Get the id of the collection
|
@@ -41,9 +46,12 @@ module Ashikawa
|
|
41
46
|
# collection = Ashikawa::Core::Collection.new database, raw_collection
|
42
47
|
# collection.id #=> 4588
|
43
48
|
attr_reader :id
|
44
|
-
|
49
|
+
|
50
|
+
# Sending requests is delegated to the database
|
51
|
+
delegate send_request: :@database
|
52
|
+
|
45
53
|
# Create a new Collection object with a name and an optional ID
|
46
|
-
#
|
54
|
+
#
|
47
55
|
# @param [Database] database The database the connection belongs to
|
48
56
|
# @param [Hash] raw_collection The raw collection returned from the server
|
49
57
|
# @api public
|
@@ -64,9 +72,9 @@ module Ashikawa
|
|
64
72
|
@id = raw_collection['id'].to_i if raw_collection.has_key? 'id'
|
65
73
|
@status = raw_collection['status'].to_i if raw_collection.has_key? 'status'
|
66
74
|
end
|
67
|
-
|
75
|
+
|
68
76
|
# Change the name of the collection
|
69
|
-
#
|
77
|
+
#
|
70
78
|
# @param [String] new_name New Name
|
71
79
|
# @return [String] New Name
|
72
80
|
# @api public
|
@@ -88,9 +96,9 @@ module Ashikawa
|
|
88
96
|
send_request_for_this_collection "/rename", put: { "name" => new_name }
|
89
97
|
@name = new_name
|
90
98
|
end
|
91
|
-
|
99
|
+
|
92
100
|
# Checks if the collection is new born
|
93
|
-
#
|
101
|
+
#
|
94
102
|
# @return [Boolean]
|
95
103
|
# @api public
|
96
104
|
# @example Is the collection new born?
|
@@ -108,9 +116,9 @@ module Ashikawa
|
|
108
116
|
def new_born?
|
109
117
|
@status == 1
|
110
118
|
end
|
111
|
-
|
119
|
+
|
112
120
|
# Checks if the collection is unloaded
|
113
|
-
#
|
121
|
+
#
|
114
122
|
# @return [Boolean]
|
115
123
|
# @api public
|
116
124
|
# @example Is the collection unloaded?
|
@@ -128,9 +136,9 @@ module Ashikawa
|
|
128
136
|
def unloaded?
|
129
137
|
@status == 2
|
130
138
|
end
|
131
|
-
|
139
|
+
|
132
140
|
# Checks if the collection is loaded
|
133
|
-
#
|
141
|
+
#
|
134
142
|
# @return [Boolean]
|
135
143
|
# @api public
|
136
144
|
# @example Is the collection loaded?
|
@@ -148,9 +156,9 @@ module Ashikawa
|
|
148
156
|
def loaded?
|
149
157
|
@status == 3
|
150
158
|
end
|
151
|
-
|
159
|
+
|
152
160
|
# Checks if the collection is in the process of being unloaded
|
153
|
-
#
|
161
|
+
#
|
154
162
|
# @return [Boolean]
|
155
163
|
# @api public
|
156
164
|
# @example Is the collection unloaded?
|
@@ -168,9 +176,9 @@ module Ashikawa
|
|
168
176
|
def being_unloaded?
|
169
177
|
@status == 4
|
170
178
|
end
|
171
|
-
|
179
|
+
|
172
180
|
# Checks if the collection is corrupted
|
173
|
-
#
|
181
|
+
#
|
174
182
|
# @return [Boolean]
|
175
183
|
# @api public
|
176
184
|
# @example Is the collection corrupted?
|
@@ -188,9 +196,9 @@ module Ashikawa
|
|
188
196
|
def corrupted?
|
189
197
|
@status > 5
|
190
198
|
end
|
191
|
-
|
199
|
+
|
192
200
|
# Does the document wait until the data has been synchronised to disk?
|
193
|
-
#
|
201
|
+
#
|
194
202
|
# @return [Boolean]
|
195
203
|
# @api public
|
196
204
|
# @example Does the collection wait for file synchronization?
|
@@ -209,9 +217,9 @@ module Ashikawa
|
|
209
217
|
server_response = send_request_for_this_collection "/properties"
|
210
218
|
server_response["waitForSync"]
|
211
219
|
end
|
212
|
-
|
220
|
+
|
213
221
|
# Change if the document will wait until the data has been synchronised to disk
|
214
|
-
#
|
222
|
+
#
|
215
223
|
# @return [String] Response from the server
|
216
224
|
# @api public
|
217
225
|
# @example Tell the collection to wait for file synchronization
|
@@ -227,11 +235,11 @@ module Ashikawa
|
|
227
235
|
# collection = Ashikawa::Core::Collection.new database, raw_collection
|
228
236
|
# collection.wait_for_sync = true
|
229
237
|
def wait_for_sync=(new_value)
|
230
|
-
|
238
|
+
send_request_for_this_collection "/properties", put: { "waitForSync" => new_value }
|
231
239
|
end
|
232
|
-
|
240
|
+
|
233
241
|
# Returns the number of documents in the collection
|
234
|
-
#
|
242
|
+
#
|
235
243
|
# @return [Fixnum] Number of documents
|
236
244
|
# @api public
|
237
245
|
# @example How many documents are in the collection?
|
@@ -250,9 +258,9 @@ module Ashikawa
|
|
250
258
|
server_response = send_request_for_this_collection "/count"
|
251
259
|
server_response["count"]
|
252
260
|
end
|
253
|
-
|
261
|
+
|
254
262
|
# Return a figure for the collection
|
255
|
-
#
|
263
|
+
#
|
256
264
|
# @param [Symbol] figure_type The figure you want to know:
|
257
265
|
# * :datafiles_count - the number of active datafiles
|
258
266
|
# * :alive_size - the total size in bytes used by all living documents
|
@@ -275,13 +283,12 @@ module Ashikawa
|
|
275
283
|
# collection.figure :datafiles_count #=> 0
|
276
284
|
def figure(figure_type)
|
277
285
|
server_response = send_request_for_this_collection "/figures"
|
278
|
-
|
279
286
|
figure_area, figure_name = figure_type.to_s.split "_"
|
280
287
|
server_response["figures"][figure_area][figure_name]
|
281
288
|
end
|
282
|
-
|
289
|
+
|
283
290
|
# Deletes the collection
|
284
|
-
#
|
291
|
+
#
|
285
292
|
# @return [String] Response from the server
|
286
293
|
# @api public
|
287
294
|
# @example Delete a collection
|
@@ -299,9 +306,9 @@ module Ashikawa
|
|
299
306
|
def delete
|
300
307
|
send_request_for_this_collection "", delete: {}
|
301
308
|
end
|
302
|
-
|
309
|
+
|
303
310
|
# Load the collection into memory
|
304
|
-
#
|
311
|
+
#
|
305
312
|
# @return [String] Response from the server
|
306
313
|
# @api public
|
307
314
|
# @example Load a collection into memory
|
@@ -319,9 +326,9 @@ module Ashikawa
|
|
319
326
|
def load
|
320
327
|
send_request_for_this_collection "/load", put: {}
|
321
328
|
end
|
322
|
-
|
329
|
+
|
323
330
|
# Load the collection into memory
|
324
|
-
#
|
331
|
+
#
|
325
332
|
# @return [String] Response from the server
|
326
333
|
# @api public
|
327
334
|
# @example Unload a collection into memory
|
@@ -339,9 +346,9 @@ module Ashikawa
|
|
339
346
|
def unload
|
340
347
|
send_request_for_this_collection "/unload", put: {}
|
341
348
|
end
|
342
|
-
|
349
|
+
|
343
350
|
# Delete all documents from the collection
|
344
|
-
#
|
351
|
+
#
|
345
352
|
# @return [String] Response from the server
|
346
353
|
# @api public
|
347
354
|
# @example Remove all documents from a collection
|
@@ -359,14 +366,13 @@ module Ashikawa
|
|
359
366
|
def truncate!
|
360
367
|
send_request_for_this_collection "/truncate", put: {}
|
361
368
|
end
|
362
|
-
|
369
|
+
|
363
370
|
# Retrieves all documents for this collection
|
364
|
-
#
|
371
|
+
#
|
365
372
|
# @note It is advised to NOT use this method due to possible HUGE data amounts requested
|
366
|
-
# @param [Hash] options Additional options for this query.
|
367
373
|
# @option options [Integer] :limit limit the maximum number of queried and returned elements.
|
368
374
|
# @option options [Integer] :skip skip the first <n> documents of the query.
|
369
|
-
# @return [
|
375
|
+
# @return [Cursor]
|
370
376
|
# @api public
|
371
377
|
# @example Get an array with all documents
|
372
378
|
# database = Ashikawa::Core::Database.new "http://localhost:8529"
|
@@ -379,25 +385,17 @@ module Ashikawa
|
|
379
385
|
# "code" => 200
|
380
386
|
# }
|
381
387
|
# collection = Ashikawa::Core::Collection.new database, raw_collection
|
382
|
-
# collection.all # =>
|
388
|
+
# collection.all # => #<Cursor id=33>
|
383
389
|
def all(options={})
|
384
|
-
|
385
|
-
|
386
|
-
request_data["limit"] = options[:limit] if options.has_key? :limit
|
387
|
-
request_data["skip"] = options[:skip] if options.has_key? :skip
|
388
|
-
|
389
|
-
server_response = @database.send_request "/simple/all", :put => request_data
|
390
|
-
|
391
|
-
documents_from_response(server_response)
|
390
|
+
send_simple_query "/simple/all", options, [:limit, :skip]
|
392
391
|
end
|
393
|
-
|
392
|
+
|
394
393
|
# Looks for documents in the collection which match the given criteria
|
395
|
-
#
|
396
|
-
# @
|
397
|
-
# @param [Hash] options Additional options for this query.
|
394
|
+
#
|
395
|
+
# @option options [Hash] :example a Hash with data matching the documents you are looking for.
|
398
396
|
# @option options [Integer] :limit limit the maximum number of queried and returned elements.
|
399
397
|
# @option options [Integer] :skip skip the first <n> documents of the query.
|
400
|
-
# @return [
|
398
|
+
# @return [Cursor]
|
401
399
|
# @api public
|
402
400
|
# @example Find all documents in the collection that are red
|
403
401
|
# database = Ashikawa::Core::Database.new "http://localhost:8529"
|
@@ -410,26 +408,45 @@ module Ashikawa
|
|
410
408
|
# "code" => 200
|
411
409
|
# }
|
412
410
|
# collection = Ashikawa::Core::Collection.new database, raw_collection
|
413
|
-
# collection.by_example { "color" => "red"} # =>
|
414
|
-
def by_example(
|
415
|
-
|
416
|
-
|
417
|
-
request_data["limit"] = options[:limit] if options.has_key? :limit
|
418
|
-
request_data["skip"] = options[:skip] if options.has_key? :skip
|
419
|
-
|
420
|
-
server_response = @database.send_request "/simple/by-example", :put => request_data
|
421
|
-
|
422
|
-
documents_from_response(server_response)
|
411
|
+
# collection.by_example example: { "color" => "red"} # => #<Cursor id=2444>
|
412
|
+
def by_example(options={})
|
413
|
+
send_simple_query "/simple/by-example", options, [:limit, :skip, :example]
|
423
414
|
end
|
424
|
-
|
415
|
+
|
416
|
+
# Looks for one document in the collection which matches the given criteria
|
417
|
+
#
|
418
|
+
# @param [Hash] example a Hash with data matching the document you are looking for.
|
419
|
+
# @return [Document]
|
420
|
+
# @api public
|
421
|
+
# @example Find one document in the collection that is red
|
422
|
+
# database = Ashikawa::Core::Database.new "http://localhost:8529"
|
423
|
+
# raw_collection = {
|
424
|
+
# "name" => "example_1",
|
425
|
+
# "waitForSync" => true,
|
426
|
+
# "id" => 4588,
|
427
|
+
# "status" => 3,
|
428
|
+
# "error" => false,
|
429
|
+
# "code" => 200
|
430
|
+
# }
|
431
|
+
# collection = Ashikawa::Core::Collection.new database, raw_collection
|
432
|
+
# collection.first_example { "color" => "red"} # => #<Document id=2444 color="red">
|
433
|
+
def first_example(example)
|
434
|
+
server_response = send_request "/simple/first-example",
|
435
|
+
put: { "collection" => @name, "example" => example }
|
436
|
+
Document.new @database, server_response
|
437
|
+
end
|
438
|
+
|
425
439
|
# Looks for documents in the collection based on location
|
426
440
|
#
|
427
|
-
# @param [Hash] options Options for this search.
|
428
441
|
# @option options [Integer] :latitude Latitude location for your search.
|
429
442
|
# @option options [Integer] :longitude Longitude location for your search.
|
430
|
-
# @
|
443
|
+
# @option options [Integer] :skip The documents to skip in the query.
|
444
|
+
# @option options [Integer] :distance If given, the attribute key used to store the distance.
|
445
|
+
# @option options [Integer] :limit The maximal amount of documents to return (default: 100).
|
446
|
+
# @option options [Integer] :geo If given, the identifier of the geo-index to use.
|
447
|
+
# @return [Cursor]
|
431
448
|
# @api public
|
432
|
-
# @example Find all documents at Infinite Loop
|
449
|
+
# @example Find all documents at Infinite Loop
|
433
450
|
# database = Ashikawa::Core::Database.new "http://localhost:8529"
|
434
451
|
# raw_collection = {
|
435
452
|
# "name" => "example_1",
|
@@ -442,23 +459,19 @@ module Ashikawa
|
|
442
459
|
# collection = Ashikawa::Core::Collection.new database, raw_collection
|
443
460
|
# collection.near latitude: 37.331693, longitude: -122.030468
|
444
461
|
def near(options={})
|
445
|
-
|
446
|
-
|
447
|
-
request_data["latitude"] = options[:latitude] if options.has_key? :latitude
|
448
|
-
request_data["longitude"] = options[:longitude] if options.has_key? :longitude
|
449
|
-
|
450
|
-
server_response = @database.send_request "/simple/near", :put => request_data
|
451
|
-
|
452
|
-
documents_from_response(server_response)
|
462
|
+
send_simple_query "/simple/near", options, [:latitude, :longitude, :distance, :skip, :limit, :geo]
|
453
463
|
end
|
454
464
|
|
455
465
|
# Looks for documents in the collection within a certain radius
|
456
466
|
#
|
457
|
-
# @param [Hash] options Options for this search.
|
458
467
|
# @option options [Integer] :latitude Latitude location for your search.
|
459
468
|
# @option options [Integer] :longitude Longitude location for your search.
|
460
469
|
# @option options [Integer] :radius Radius around the given location you want to search in.
|
461
|
-
# @
|
470
|
+
# @option options [Integer] :skip The documents to skip in the query.
|
471
|
+
# @option options [Integer] :distance If given, the attribute key used to store the distance.
|
472
|
+
# @option options [Integer] :limit The maximal amount of documents to return (default: 100).
|
473
|
+
# @option options [Integer] :geo If given, the identifier of the geo-index to use.
|
474
|
+
# @return [Cursor]
|
462
475
|
# @api public
|
463
476
|
# @example Find all documents within a radius of 100 to Infinite Loop
|
464
477
|
# database = Ashikawa::Core::Database.new "http://localhost:8529"
|
@@ -473,26 +486,101 @@ module Ashikawa
|
|
473
486
|
# collection = Ashikawa::Core::Collection.new database, raw_collection
|
474
487
|
# collection.within latitude: 37.331693, longitude: -122.030468, radius: 100
|
475
488
|
def within(options={})
|
476
|
-
|
477
|
-
|
478
|
-
request_data["latitude"] = options[:latitude] if options.has_key? :latitude
|
479
|
-
request_data["longitude"] = options[:longitude] if options.has_key? :longitude
|
480
|
-
request_data["radius"] = options[:radius] if options.has_key? :radius
|
489
|
+
send_simple_query "/simple/within", options, [:latitude, :longitude, :radius, :distance, :skip, :limit, :geo]
|
490
|
+
end
|
481
491
|
|
482
|
-
server_response = @database.send_request "/simple/within", :put => request_data
|
483
492
|
|
484
|
-
|
493
|
+
# Looks for documents in the collection with an attribute between two values
|
494
|
+
#
|
495
|
+
# @option options [Integer] :attribute The attribute path to check.
|
496
|
+
# @option options [Integer] :left The lower bound
|
497
|
+
# @option options [Integer] :right The upper bound
|
498
|
+
# @option options [Integer] :closed If true, use intervall including left and right, otherwise exclude right, but include left.
|
499
|
+
# @option options [Integer] :skip The documents to skip in the query (optional).
|
500
|
+
# @option options [Integer] :limit The maximal amount of documents to return (optional).
|
501
|
+
# @return [Cursor]
|
502
|
+
# @api public
|
503
|
+
def in_range(options={})
|
504
|
+
send_simple_query "/simple/range", options, [:attribute, :left, :right, :closed, :limit, :skip]
|
485
505
|
end
|
486
506
|
|
487
507
|
# Fetch a certain document by its ID
|
488
|
-
#
|
508
|
+
#
|
489
509
|
# @param [Integer] document_id the id of the document
|
510
|
+
# @raise [DocumentNotFoundException] If the requested document was not found
|
490
511
|
# @return Document
|
491
512
|
# @api public
|
492
513
|
# @example Fetch a document with the ID 12345
|
493
514
|
# document = collection[12345]
|
494
515
|
def [](document_id)
|
495
|
-
|
516
|
+
begin
|
517
|
+
server_response = send_request "/document/#{@id}/#{document_id}"
|
518
|
+
rescue RestClient::ResourceNotFound
|
519
|
+
raise DocumentNotFoundException
|
520
|
+
end
|
521
|
+
|
522
|
+
Document.new @database, server_response
|
523
|
+
end
|
524
|
+
|
525
|
+
# Replace a certain document by its ID
|
526
|
+
#
|
527
|
+
# @param [Integer] document_id the id of the document
|
528
|
+
# @param [Hash] raw_document the data you want to replace it with
|
529
|
+
# @api public
|
530
|
+
def []=(document_id, raw_document)
|
531
|
+
send_request "/document/#{@id}/#{document_id}", put: raw_document
|
532
|
+
end
|
533
|
+
|
534
|
+
# Create a document with given raw data
|
535
|
+
#
|
536
|
+
# @param [Hash] raw_document
|
537
|
+
# @return DocumentHash
|
538
|
+
# @api public
|
539
|
+
def create(raw_document)
|
540
|
+
server_response = send_request "/document?collection=#{@id}",
|
541
|
+
post: raw_document
|
542
|
+
|
543
|
+
Document.new @database, server_response
|
544
|
+
end
|
545
|
+
|
546
|
+
alias :<< :create
|
547
|
+
|
548
|
+
# Add an index to the collection
|
549
|
+
#
|
550
|
+
# @param [Symbol] type What kind of index?
|
551
|
+
# @option opts [Array<Symbol>] on On which fields?
|
552
|
+
# @return Index
|
553
|
+
# @api public
|
554
|
+
def add_index(type, opts)
|
555
|
+
server_response = send_request "/index?collection=#{@id}", post: {
|
556
|
+
"type" => type.to_s,
|
557
|
+
"fields" => opts[:on].map { |field| field.to_s }
|
558
|
+
}
|
559
|
+
|
560
|
+
Index.new self, server_response
|
561
|
+
end
|
562
|
+
|
563
|
+
# Get an index by ID
|
564
|
+
#
|
565
|
+
# @param [Int] id
|
566
|
+
# @return Index
|
567
|
+
# @api public
|
568
|
+
def index(id)
|
569
|
+
server_response = send_request "/index/#{@id}/#{id}"
|
570
|
+
|
571
|
+
Index.new self, server_response
|
572
|
+
end
|
573
|
+
|
574
|
+
# Get all indices
|
575
|
+
#
|
576
|
+
# @return [Array<Index>]
|
577
|
+
# @api public
|
578
|
+
def indices
|
579
|
+
server_response = send_request "/index?collection=#{@id}"
|
580
|
+
|
581
|
+
server_response["indexes"].map do |raw_index|
|
582
|
+
Index.new self, raw_index
|
583
|
+
end
|
496
584
|
end
|
497
585
|
|
498
586
|
private
|
@@ -502,22 +590,25 @@ module Ashikawa
|
|
502
590
|
# @return [String] Response from the server
|
503
591
|
# @api private
|
504
592
|
def send_request_for_this_collection(path, method={})
|
505
|
-
|
506
|
-
@database.send_request "/collection/#{id}#{path}"
|
507
|
-
else
|
508
|
-
@database.send_request "/collection/#{id}#{path}", method
|
509
|
-
end
|
593
|
+
send_request "/collection/#{id}#{path}", method
|
510
594
|
end
|
511
595
|
|
512
|
-
#
|
513
|
-
#
|
514
|
-
# @param [
|
515
|
-
# @
|
596
|
+
# Send a simple query to the server
|
597
|
+
#
|
598
|
+
# @param [String] path The path for the request
|
599
|
+
# @param [Hash] options The options given to the method
|
600
|
+
# @param [Array<Symbol>] keys The required keys
|
601
|
+
# @return [Hash] The parsed hash for the request
|
516
602
|
# @api private
|
517
|
-
def
|
518
|
-
|
519
|
-
|
603
|
+
def send_simple_query(path, options, keys)
|
604
|
+
request_data = { "collection" => @name }
|
605
|
+
|
606
|
+
keys.each do |key|
|
607
|
+
request_data[key.to_s] = options[key] if options.has_key? key
|
520
608
|
end
|
609
|
+
|
610
|
+
server_response = send_request path, :put => request_data
|
611
|
+
Cursor.new @database, server_response
|
521
612
|
end
|
522
613
|
end
|
523
614
|
end
|