jor 0.1.1

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.
@@ -0,0 +1,62 @@
1
+
2
+ module JOR
3
+ class Doc
4
+
5
+ def self.paths(path,h)
6
+ if h.class==Hash
7
+ v = []
8
+ h.each do |k,val|
9
+ if JOR::Storage::SELECTORS_ALL.member?(k)
10
+ return [{"path_to" => path, "obj" => h, "class" => h.class, "selector" => true}]
11
+ else
12
+ raise InvalidFieldName.new(k) if ((k!="_id") && (k!="_created_at") && (k!="_updated_at")) && (k[0]=="_" || k[0]=="$")
13
+ v << paths("#{path}/#{k}",val)
14
+ end
15
+ end
16
+ return v.flatten
17
+ else
18
+ if h.class==Array
19
+ v = []
20
+ if h.size>0
21
+ h.each do |item|
22
+ v << paths("#{path}",item)
23
+ end
24
+ else
25
+ v << ["#{path}"]
26
+ end
27
+ return v.flatten
28
+ else
29
+ return [{"path_to" => path, "obj" => h, "class" => h.class}]
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.difference(set, set_to_substract)
35
+ return set if set_to_substract.nil? || set_to_substract.size==0
36
+
37
+ to_exclude = []
38
+ set_to_substract.each do |item|
39
+ raise FieldIdCannotBeExcludedFromIndex.new unless item["path_to"].match(/\/_id/)==nil
40
+ to_exclude << Regexp.new("^#{item["path_to"]}")
41
+ end
42
+
43
+ res = []
44
+ set.each do |item|
45
+ not_found = true
46
+ to_exclude.each do |re|
47
+ not_found = not_found && re.match(item["path_to"])==nil
48
+ end
49
+ res << item if not_found
50
+ end
51
+ return res
52
+ end
53
+
54
+ def self.deep_merge(dest, source)
55
+ res = Hash.new
56
+ dest.merge(source) do |key, old_v, new_v|
57
+ res[key] = ((old_v.class == Hash) && (new_v.class == Hash)) ? deep_merge(old_v, new_v) : new_v
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,96 @@
1
+
2
+ module JOR
3
+ class Error < RuntimeError
4
+ end
5
+
6
+ class NoResults < Error
7
+ def initialize(doc)
8
+ super %(no results found for "#{doc}")
9
+ end
10
+ end
11
+
12
+ class TypeNotSupported < Error
13
+ def initialize(class_name)
14
+ super %(Type #{class_name} not supported)
15
+ end
16
+ end
17
+
18
+ class InvalidFieldName < Error
19
+ def initialize(field)
20
+ super %(Invalid character in field name "#{field}". Cannot start with '_' or '$')
21
+ end
22
+ end
23
+
24
+ class InvalidDocumentId < Error
25
+ def initialize(id)
26
+ super %(The document "_id" must be a positive integer (>=0), #{id} is not valid)
27
+ end
28
+ end
29
+
30
+ class DocumentIdAlreadyExists < Error
31
+ def initialize(id, name)
32
+ super %(A document with _id #{id} already exists in collection "{name}")
33
+ end
34
+ end
35
+
36
+ class DocumentNeedsId < Error
37
+ def initialize(name)
38
+ super %(The collection #{name} is not auto-incremental. You must define the "_id" of the document")
39
+ end
40
+ end
41
+
42
+ class DocumentDoesNotNeedId < Error
43
+ def initialize(name)
44
+ super %(The collection #{name} is auto-incremental. You must not define the "_id" of the document")
45
+ end
46
+ end
47
+
48
+ class IncompatibleSelectors < Error
49
+ def initialize(str)
50
+ super %(Incompatible selectors in "#{str}". They must be grouped like this #{Storage::SELECTORS})
51
+ end
52
+ end
53
+
54
+ class NotInCollection < Error
55
+ def initialize
56
+ super %(The current collection is undefined)
57
+ end
58
+ end
59
+
60
+ class CollectionDoesNotExist < Error
61
+ def initialize(str)
62
+ super %(Collection "#{str}" does not exist)
63
+ end
64
+ end
65
+
66
+ class CollectionAlreadyExists < Error
67
+ def initialize(str)
68
+ super %(Collection "#{str}" already exists)
69
+ end
70
+ end
71
+
72
+ class CollectionNotValid < Error
73
+ def initialize(str)
74
+ super %(Collection "#{str}" is not a valid name, might be reserved)
75
+ end
76
+ end
77
+
78
+ class FieldIdCannotBeExcludedFromIndex < Error
79
+ def initialize
80
+ super %(Field _id cannot be excluded from the index)
81
+ end
82
+ end
83
+
84
+ class CouldNotFindPathToFromIndex < Error
85
+ def initialize(str)
86
+ super %(Could not find path_to from index #{str})
87
+ end
88
+ end
89
+
90
+ class CouldNotFindPathToFromIndex < Error
91
+ def initialize(index, id)
92
+ super %(Unknown index #{index} in document #{id})
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,52 @@
1
+
2
+ module JOR
3
+ class Server
4
+
5
+ def initialize(redis = nil)
6
+ ## defaults to test db on redis
7
+ redis ||= Redis.new(:db => 9, :driver => :hiredis)
8
+ @jor = JOR::Storage.new(redis)
9
+ end
10
+
11
+ def call(env)
12
+ req = Rack::Request.new(env)
13
+ method = req.path
14
+
15
+ if env["REQUEST_METHOD"]!="PUT"
16
+ return [422, {"Content-Type" => "application/json"}, [{"error" => "only method accepted is PUT"}.to_json]]
17
+ end
18
+
19
+ clean_methods = method.gsub("/","").split(".")
20
+ clean_methods.map!(&:to_sym)
21
+
22
+ args = req.params["args"]
23
+ clean_args = []
24
+ body_str = req.body.read
25
+ clean_args = JSON::parse(body_str) unless body_str.nil? || body_str.empty?
26
+
27
+ begin
28
+ obj = @jor
29
+ res = nil
30
+
31
+ clean_methods.each_with_index do |meth, i|
32
+ if i==clean_methods.size()-1
33
+ res = obj.public_send(meth,*clean_args)
34
+ else
35
+ obj = obj.public_send(meth)
36
+ end
37
+ end
38
+
39
+ if res.class==Hash || res.class==Array
40
+ return [200, {"Content-Type" => "application/json"}, [res.to_json]]
41
+ else
42
+ return [200, {"Content-Type" => "application/json"}, [{"value" => res}.to_json]]
43
+ end
44
+ rescue Exception => e
45
+ return [422, {"Content-Type" => "application/json"}, [{"error" => e.message}.to_json]]
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+
52
+
@@ -0,0 +1,88 @@
1
+
2
+ module JOR
3
+ class Storage
4
+
5
+ NAMESPACE = "jor"
6
+
7
+ SELECTORS = {
8
+ :compare => ["$gt","$gte","$lt","$lte"],
9
+ :sets => ["$in","$all","$not"]
10
+ }
11
+
12
+ SELECTORS_ALL = SELECTORS.keys.inject([]) { |sel, element| sel | SELECTORS[element] }
13
+
14
+ def initialize(redis_client = nil)
15
+ redis_client.nil? ? @redis = Redis.new() : @redis = redis_client
16
+ end
17
+
18
+ def redis
19
+ @redis
20
+ end
21
+
22
+ def collections
23
+ redis.smembers("#{Storage::NAMESPACE}/collections")
24
+ end
25
+
26
+ def create_collection(name, options = {:auto_increment => false})
27
+ options = {:auto_increment => false}.merge(options.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo})
28
+ raise CollectionNotValid.new(name) if self.respond_to?(name)
29
+ is_new = redis.sadd("#{Storage::NAMESPACE}/collections",name)
30
+ raise CollectionAlreadyExists.new(name) if (is_new==false or is_new==0)
31
+ redis.set("#{Storage::NAMESPACE}/collection/#{name}/auto-increment", options[:auto_increment])
32
+ name
33
+ end
34
+
35
+ def destroy_collection(name)
36
+ coll_to_be_removed = find_collection(name)
37
+ coll_to_be_removed.delete({})
38
+ redis.pipelined do
39
+ redis.srem("#{Storage::NAMESPACE}/collections",name)
40
+ redis.del("#{Storage::NAMESPACE}/collection/#{name}/auto-increment")
41
+ end
42
+ name
43
+ end
44
+
45
+ def destroy_all()
46
+ collections.each do |col|
47
+ destroy_collection(col)
48
+ end
49
+ end
50
+
51
+ def info
52
+ res = {}
53
+ ri = redis.info
54
+
55
+ res["used_memory_in_redis"] = ri["used_memory"].to_i
56
+ res["num_collections"] = collections.size
57
+
58
+ res["collections"] = {}
59
+ collections.each do |c|
60
+ coll = find_collection(c)
61
+ res["collections"][coll.name] = {}
62
+ res["collections"][coll.name]["num_documents"] = coll.count
63
+ res["collections"][coll.name]["auto_increment"] = coll.auto_increment?
64
+ end
65
+
66
+ res
67
+ end
68
+
69
+ protected
70
+
71
+ def method_missing(method)
72
+ find_collection(method)
73
+ end
74
+
75
+ def find_collection(method)
76
+ redis_auto_incr = redis.get("#{Storage::NAMESPACE}/collection/#{method}/auto-increment")
77
+ if (redis_auto_incr=="true")
78
+ auto_increment = true
79
+ elsif (redis_auto_incr=="false")
80
+ auto_increment = false
81
+ else
82
+ raise CollectionDoesNotExist.new(method.to_s)
83
+ end
84
+ Collection.new(self, method, auto_increment)
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,3 @@
1
+ module JOR
2
+ VERSION = '0.1.1'
3
+ end
@@ -0,0 +1,11 @@
1
+ require 'test/unit'
2
+ require 'rack/test'
3
+ require 'json'
4
+ require 'hiredis'
5
+ require 'redis'
6
+
7
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
8
+ Dir[File.dirname(__FILE__) + '/test_helpers/**/*.rb'].each { |file| require file }
9
+ Dir[File.dirname(__FILE__) + '/unit/test_case.rb'].each { |file| require file }
10
+
11
+ require 'jor'
@@ -0,0 +1,71 @@
1
+ module TestHelpers
2
+ module Fixtures
3
+
4
+ def create_sample_doc_cs(partial_doc = {})
5
+ doc = {
6
+ "_id" => 1,
7
+ "name" => {
8
+ "first" => "John",
9
+ "last" => "Backus"
10
+ },
11
+ "birth" => Time.mktime("1924","12","03","05","00","00").to_i,
12
+ "death" => Time.mktime("2007","03","17","04","00","00").to_i,
13
+ "contribs" => [ "Fortran", "ALGOL", "Backus-Naur Form", "FP" ],
14
+ "awards" => [
15
+ {
16
+ "award" => "W.W. McDowellAward",
17
+ "year" => 1967,
18
+ "by" => "IEEE Computer Society"
19
+ },
20
+ {
21
+ "award" => "National Medal of Science",
22
+ "year" => 1975,
23
+ "by" => "National Science Foundation"
24
+ },
25
+ {
26
+ "award" => "Turing Award",
27
+ "year" => 1977,
28
+ "by" => "ACM"
29
+ },
30
+ {
31
+ "award" => "Draper Prize",
32
+ "year" => 1993,
33
+ "by" => "National Academy of Engineering"
34
+ }
35
+ ]
36
+ }
37
+ doc.merge(partial_doc)
38
+ end
39
+
40
+ def create_sample_doc_restaurant(partial_doc = {})
41
+ doc = {
42
+ "_id" => 1,
43
+ "name" => "restaurant",
44
+ "stars" => 3,
45
+ "cuisine" => ["asian", "japanese"],
46
+ "address" => {
47
+ "address" => "Main St 100",
48
+ "city" => "Ann Arbor",
49
+ "zipcode" => "08104"
50
+ },
51
+ "description" => "very long description that we might not want to index",
52
+ "wines" => [
53
+ {
54
+ "name" => "wine1",
55
+ "year" => 1998,
56
+ "type" => ["garnatxa", "merlot"]
57
+ },
58
+ {
59
+ "name" => "wine2",
60
+ "year" => 2009,
61
+ "type" => ["syrah", "merlot"]
62
+ },
63
+ ]
64
+ }
65
+ doc.merge(partial_doc)
66
+ end
67
+
68
+ end
69
+ end
70
+
71
+ Test::Unit::TestCase.send(:include, TestHelpers::Fixtures)
@@ -0,0 +1,884 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class CollectionTest < JOR::Test::Unit::TestCase
4
+
5
+ def setup
6
+ super
7
+ @jor.create_collection("test")
8
+ end
9
+
10
+ def test_basic_insert_and_find_path
11
+
12
+ doc1 = create_sample_doc_restaurant({"_id" => 1})
13
+ @jor.test.insert(doc1)
14
+
15
+ doc2 = create_sample_doc_restaurant({"_id" => 2})
16
+ @jor.test.insert(doc2)
17
+
18
+ doc3 = create_sample_doc_restaurant({"_id" => 3})
19
+ @jor.test.insert(doc3)
20
+
21
+ assert_equal 3, @jor.test.count()
22
+ assert_equal 3, @jor.test.find({}).size
23
+
24
+ assert_equal doc1.to_json, @jor.test.find({"_id" => 1}).first.to_json
25
+ assert_equal doc2.to_json, @jor.test.find({"_id" => 2}).first.to_json
26
+ assert_equal doc3.to_json, @jor.test.find({"_id" => 3}).first.to_json
27
+ end
28
+
29
+ def test_bulk_insert
30
+
31
+ sample_docs = []
32
+ 10.times do |i|
33
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}"})
34
+ end
35
+
36
+ assert_equal 10, @jor.test.count()
37
+
38
+ docs = @jor.test.find({})
39
+ 10.times do |i|
40
+ assert_equal sample_docs[i].to_json, docs[i].to_json
41
+ end
42
+
43
+ end
44
+
45
+ def test_delete
46
+ sample_docs = []
47
+ 10.times do |i|
48
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "foo" => "bar", "year" => 2000+i, "num" => 666 })
49
+ end
50
+
51
+ assert_equal 10, @jor.test.count()
52
+
53
+ assert_equal 0, @jor.test.delete({"_id" => 42})
54
+ assert_equal 10, @jor.test.count()
55
+
56
+ assert_equal 0, @jor.test.delete({"foo" => "not_bar"})
57
+ assert_equal 10, @jor.test.count()
58
+
59
+ assert_equal 1, @jor.test.delete({"_id" => 0})
60
+ assert_equal 9, @jor.test.count()
61
+
62
+ assert_equal 3, @jor.test.delete({"year" => { "$lt" => 2004 }})
63
+ assert_equal 6, @jor.test.count()
64
+
65
+ assert_equal ["4","5","6","7","8","9"].sort, @jor.redis.smembers("#{JOR::Storage::NAMESPACE}/test/idx/!/foo/String/bar").sort
66
+ assert_equal ["4","5","6","7","8","9"].sort, @jor.redis.smembers("#{JOR::Storage::NAMESPACE}/test/idx/!/num/Numeric/666").sort
67
+ assert_equal ["4","5","6","7","8","9"].sort, @jor.redis.zrange("#{JOR::Storage::NAMESPACE}/test/idx/!/num/Numeric",0,-1).sort
68
+
69
+ assert_equal 6, @jor.test.delete({"foo" => "bar"})
70
+ assert_equal 0, @jor.test.count()
71
+
72
+ assert_equal [], @jor.redis.smembers("#{JOR::Storage::NAMESPACE}/test/idx/!/num/String/bar")
73
+ assert_equal [], @jor.redis.smembers("#{JOR::Storage::NAMESPACE}/test/idx/!/num/Numeric/666")
74
+ assert_equal [].sort, @jor.redis.zrange("#{JOR::Storage::NAMESPACE}/test/idx/!/num/Numeric",0,-1).sort
75
+
76
+ assert_equal @jor.redis.keys("#{JOR::Storage::NAMESPACE}/test/idx/*"), []
77
+
78
+ end
79
+
80
+ def test_find_exact_string
81
+ sample_docs = []
82
+ 10.times do |i|
83
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}"})
84
+ end
85
+
86
+ doc = @jor.test.find({"name" => "foo_5"}).first
87
+ assert_equal sample_docs[5].to_json, doc.to_json
88
+
89
+ doc = @jor.test.find({"name" => "foo_7"}).first
90
+ assert_equal sample_docs[7].to_json, doc.to_json
91
+ end
92
+
93
+ def test_find_empty
94
+ assert_equal [], @jor.test.find({})
95
+ assert_equal [], @jor.test.find({"year" => 200})
96
+ assert_equal [], @jor.test.find({"_id" => 200})
97
+ end
98
+
99
+ def test_find_by_comparison_selector
100
+
101
+ sample_docs = []
102
+ ## years from 2000 to 2009
103
+ 10.times do |i|
104
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "year" => 2000+i})
105
+ end
106
+
107
+ doc = @jor.test.find({"year" => 2005}).first
108
+ assert_equal sample_docs[5].to_json, doc.to_json
109
+
110
+ doc = @jor.test.find({"year" => { "$lt" => 2005 }})
111
+ assert_equal 5, doc.size
112
+ assert_equal sample_docs[0].to_json, doc.first.to_json
113
+ assert_equal sample_docs[4].to_json, doc.last.to_json
114
+
115
+ doc = @jor.test.find({"year" => { "$lte" => 2005 }})
116
+ assert_equal 6, doc.size
117
+ assert_equal sample_docs[0].to_json, doc.first.to_json
118
+ assert_equal sample_docs[5].to_json, doc.last.to_json
119
+
120
+ doc = @jor.test.find({"year" => { "$gt" => 2007 }})
121
+ assert_equal 2, doc.size
122
+ assert_equal sample_docs[8].to_json, doc.first.to_json
123
+ assert_equal sample_docs[9].to_json, doc.last.to_json
124
+
125
+ doc = @jor.test.find({"year" => { "$gte" => 2007 }})
126
+ assert_equal 3, doc.size
127
+ assert_equal sample_docs[7].to_json, doc.first.to_json
128
+ assert_equal sample_docs[9].to_json, doc.last.to_json
129
+
130
+ doc = @jor.test.find({"year" => { "$gte" => 2003, "$lt" => 2005 }})
131
+ assert_equal 2, doc.size
132
+ assert_equal sample_docs[3].to_json, doc.first.to_json
133
+ assert_equal sample_docs[4].to_json, doc.last.to_json
134
+
135
+ doc = @jor.test.find({"year" => { "$gt" => 2003, "$lt" => 9999 }})
136
+ assert_equal 6, doc.size
137
+ assert_equal sample_docs[4].to_json, doc.first.to_json
138
+ assert_equal sample_docs[9].to_json, doc.last.to_json
139
+
140
+ end
141
+
142
+ def test_find_by_comparison_combined
143
+
144
+ sample_docs = []
145
+ ## years from 2000 to 2009
146
+ 10.times do |i|
147
+ sample_docs << @jor.test.insert({"_id" => i, "year" => 2000+i, "desc" => "bar", "nested" => {"name" => "foo_#{i}", "quantity" => i.to_f}})
148
+ end
149
+
150
+ docs = @jor.test.find({"year" => { "$gt" => 2001, "$lt" => 2009 }, "nested" => {"quantity" => {"$lt" => 1.0}}})
151
+ assert_equal 0, docs.size
152
+ assert_equal [], docs
153
+
154
+ docs = @jor.test.find({"year" => { "$gt" => 2001, "$lt" => 2009 }, "nested" => {"quantity" => {"$lt" => 4.0}}})
155
+ assert_equal 2, docs.size
156
+ assert_equal sample_docs[2].to_json, docs.first.to_json
157
+ assert_equal sample_docs[3].to_json, docs.last.to_json
158
+
159
+ docs = @jor.test.find({"year" => { "$gt" => 2001, "$lt" => 2009 }, "nested" => {"name" => "foo_#{4}", "quantity" => {"$lte" => 4.0}}})
160
+ assert_equal 1, docs.size
161
+ assert_equal sample_docs[4].to_json, docs.first.to_json
162
+
163
+ docs = @jor.test.find({"year" => { "$gt" => 2001, "$lt" => 2009 }, "desc" => "bar", "nested" => {"name" => "foo_#{4}", "quantity" => {"$lte" => 4.0}}})
164
+ assert_equal 1, docs.size
165
+ assert_equal sample_docs[4].to_json, docs.first.to_json
166
+
167
+ docs = @jor.test.find({"year" => { "$gt" => 2001, "$lt" => 2009 }, "desc" => "NOT_bar", "nested" => {"name" => "foo_#{4}", "quantity" => {"$lte" => 4.0}}})
168
+ assert_equal 0, docs.size
169
+
170
+ end
171
+
172
+ def test_find_by_set_selector
173
+
174
+ sample_docs = []
175
+ ## years from 2000 to 2009
176
+ 10.times do |i|
177
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "nested" => { "year" => 2000+i, "pair" => ((i%2)==0 ? "even" : "odd")} })
178
+ end
179
+
180
+ docs = @jor.test.find({"_id" => {"$in" => []}})
181
+ assert_equal 0, docs.size
182
+
183
+ docs = @jor.test.find({"_id" => {"$in" => [42]}})
184
+ assert_equal 0, docs.size
185
+
186
+ docs = @jor.test.find({"_id" => {"$in" => [8]}})
187
+ assert_equal 1, docs.size
188
+ assert_equal sample_docs[8].to_json, docs.first.to_json
189
+
190
+ docs = @jor.test.find({"_id" => {"$all" => [8]}})
191
+ assert_equal 1, docs.size
192
+ assert_equal sample_docs[8].to_json, docs.first.to_json
193
+
194
+ docs = @jor.test.find({"_id" => {"$in" => [1, 2, 3, 4, 42]}})
195
+ assert_equal 4, docs.size
196
+ assert_equal sample_docs[1].to_json, docs.first.to_json
197
+ assert_equal sample_docs[4].to_json, docs.last.to_json
198
+
199
+ docs = @jor.test.find({"_id" => {"$all" => [1, 2, 3, 4, 42]}})
200
+ assert_equal 0, docs.size
201
+
202
+ docs = @jor.test.find({"name" => {"$in" => ["foo_42"]}})
203
+ assert_equal 0, docs.size
204
+
205
+ docs = @jor.test.find({"name" => {"$all" => ["foo_42"]}})
206
+ assert_equal 0, docs.size
207
+
208
+ docs = @jor.test.find({"name" => {"$in" => []}})
209
+ assert_equal 0, docs.size
210
+
211
+ docs = @jor.test.find({"name" => {"$all" => []}})
212
+ assert_equal 0, docs.size
213
+
214
+ docs = @jor.test.find({"name" => {"$in" => ["foo_7", "foo_8", "foo_42"]}})
215
+ assert_equal 2, docs.size
216
+ assert_equal sample_docs[7].to_json, docs.first.to_json
217
+ assert_equal sample_docs[8].to_json, docs.last.to_json
218
+
219
+ docs = @jor.test.find({"nested" => {"pair" => { "$in" => ["even", "odd"]}}})
220
+ assert_equal 10, docs.size
221
+ assert_equal sample_docs[0].to_json, docs.first.to_json
222
+ assert_equal sample_docs[9].to_json, docs.last.to_json
223
+
224
+ docs = @jor.test.find({"nested" => {"pair" => { "$all" => ["even", "odd"]}}})
225
+ assert_equal 0, docs.size
226
+
227
+ docs = @jor.test.find({"nested" => {"pair" => { "$in" => ["even"]}}})
228
+ assert_equal 5, docs.size
229
+ assert_equal sample_docs[0].to_json, docs.first.to_json
230
+ assert_equal sample_docs[8].to_json, docs.last.to_json
231
+
232
+ docs = @jor.test.find({"nested" => {"pair" => { "$all" => ["even"]}}})
233
+ assert_equal 5, docs.size
234
+ assert_equal sample_docs[0].to_json, docs.first.to_json
235
+ assert_equal sample_docs[8].to_json, docs.last.to_json
236
+
237
+ docs = @jor.test.find({"nested" => {"pair" => { "$in" => ["even", "fake"]}}})
238
+ assert_equal 5, docs.size
239
+ assert_equal sample_docs[0].to_json, docs.first.to_json
240
+ assert_equal sample_docs[8].to_json, docs.last.to_json
241
+
242
+ docs = @jor.test.find({"nested" => {"pair" => { "$all" => ["even", "fake"]}}})
243
+ assert_equal 0, docs.size
244
+
245
+ end
246
+
247
+ def test_find_by_not_selector
248
+
249
+ sample_docs = []
250
+ ## years from 2000 to 2009
251
+ 10.times do |i|
252
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "nested" => { "year" => 2000+i, "even" => ((i%2)==0 ? true : false)} })
253
+ end
254
+
255
+ docs = @jor.test.find({"_id" => {"$not" => 3}})
256
+ assert_equal 9, docs.size
257
+ docs.each do |doc|
258
+ assert_not_equal 3, doc["_id"]
259
+ end
260
+
261
+ docs = @jor.test.find({"_id" => {"$not" => [3]}})
262
+ assert_equal 9, docs.size
263
+ docs.each do |doc|
264
+ assert_not_equal 3, doc["_id"]
265
+ end
266
+
267
+ docs = @jor.test.find({"_id" => {"$not" => [1, 3, 4, 42]}})
268
+ assert_equal 7, docs.size
269
+ docs.each do |doc|
270
+ assert_not_equal 1, doc["_id"]
271
+ assert_not_equal 3, doc["_id"]
272
+ assert_not_equal 4, doc["_id"]
273
+ assert_not_equal 42, doc["_id"]
274
+ end
275
+
276
+ docs = @jor.test.find({"_id" => {"$not" => [3]}})
277
+ assert_equal 9, docs.size
278
+ docs.each do |doc|
279
+ assert_not_equal 3, doc["_id"]
280
+ end
281
+
282
+ docs = @jor.test.find({"name" => {"$not" => "foo_3"}})
283
+ assert_equal 9, docs.size
284
+ docs.each do |doc|
285
+ assert_not_equal 3, doc["_id"]
286
+ end
287
+
288
+ docs = @jor.test.find({"name" => {"$not" => ["foo_3"]}})
289
+ assert_equal 9, docs.size
290
+ docs.each do |doc|
291
+ assert_not_equal 3, doc["_id"]
292
+ end
293
+
294
+ docs = @jor.test.find({"name" => {"$not" => ["foo_1", "foo_3", "foo_4", "foo_42"]}})
295
+ assert_equal 7, docs.size
296
+ docs.each do |doc|
297
+ assert_not_equal 1, doc["_id"]
298
+ assert_not_equal 3, doc["_id"]
299
+ assert_not_equal 4, doc["_id"]
300
+ assert_not_equal 42, doc["_id"]
301
+ end
302
+
303
+ docs = @jor.test.find({"nested" => {"year" => {"$not" => 2004}}})
304
+ assert_equal 9, docs.size
305
+ docs.each do |doc|
306
+ assert_not_equal 4, doc["_id"]
307
+ end
308
+
309
+ docs = @jor.test.find({"nested" => {"year" => {"$not" => [2004, 2009]}}})
310
+ assert_equal 8, docs.size
311
+ docs.each do |doc|
312
+ assert_not_equal 4, doc["_id"]
313
+ assert_not_equal 9, doc["_id"]
314
+ end
315
+
316
+ docs = @jor.test.find({"nested" => {"even" => true}})
317
+ assert_equal 5, docs.size
318
+ docs.each do |doc|
319
+ assert_equal 0, doc["_id"]%2
320
+ end
321
+
322
+ docs = @jor.test.find({"nested" => {"even" => {"$not" => false}}})
323
+ assert_equal 5, docs.size
324
+ docs.each do |doc|
325
+ assert_equal 0, doc["_id"]%2
326
+ end
327
+
328
+
329
+
330
+
331
+ end
332
+
333
+ def test_playing_with_find_options
334
+
335
+ n = (JOR::Collection::DEFAULT_OPTIONS[:max_documents]+100)
336
+
337
+ n.times do |i|
338
+ doc = create_sample_doc_restaurant({"_id" => i})
339
+ @jor.test.insert(doc)
340
+ end
341
+
342
+ ## testing max_documents
343
+
344
+ docs = @jor.test.find({})
345
+
346
+ assert_equal JOR::Collection::DEFAULT_OPTIONS[:max_documents], docs.size
347
+ assert_equal 0, docs.first["_id"]
348
+ assert_equal JOR::Collection::DEFAULT_OPTIONS[:max_documents]-1, docs.last["_id"]
349
+
350
+ docs = @jor.test.find({},{:max_documents => 20})
351
+ assert_equal 20, docs.size
352
+
353
+ docs = @jor.test.find({},{:max_documents => -1})
354
+ assert_equal n, docs.size
355
+ assert_equal 0, docs.first["_id"]
356
+ assert_equal n-1, docs.last["_id"]
357
+
358
+ ## testing only_ids
359
+
360
+ docs = @jor.test.find({},{:only_ids => true, :max_documents => -1})
361
+ assert_equal n, docs.size
362
+ assert_equal 0, docs.first
363
+ assert_equal n-1, docs.last
364
+
365
+ docs = @jor.test.find({},{:only_ids => true})
366
+ assert_equal JOR::Collection::DEFAULT_OPTIONS[:max_documents], docs.size
367
+ assert_equal 0, docs.first
368
+ assert_equal JOR::Collection::DEFAULT_OPTIONS[:max_documents]-1, docs.last
369
+
370
+ ## testing reversed
371
+
372
+ docs = @jor.test.find({},{:only_ids => true, :max_documents => -1, :reversed => true})
373
+ assert_equal n, docs.size
374
+ assert_equal n-1, docs.first
375
+ assert_equal 0, docs.last
376
+
377
+ docs = @jor.test.find({},{:only_ids => true, :reversed => true})
378
+ assert_equal JOR::Collection::DEFAULT_OPTIONS[:max_documents], docs.size
379
+ assert_equal n-1, docs.first
380
+ assert_equal n-JOR::Collection::DEFAULT_OPTIONS[:max_documents], docs.last
381
+
382
+ ## encoded false
383
+
384
+ docs = @jor.test.find({},{:raw => true, :reversed => true})
385
+ assert_equal JOR::Collection::DEFAULT_OPTIONS[:max_documents], docs.size
386
+ assert_equal String, docs.first.class
387
+ assert_equal String, docs.last.class
388
+ assert_equal n-1, JSON::parse(docs.first)["_id"]
389
+ assert_equal n-JOR::Collection::DEFAULT_OPTIONS[:max_documents], JSON::parse(docs.last)["_id"]
390
+
391
+ end
392
+
393
+ def test_exclude_indexes
394
+
395
+ assert_raise JOR::FieldIdCannotBeExcludedFromIndex do
396
+ @jor.test.insert(create_sample_doc_restaurant({"_id" => 1}),
397
+ {:excluded_fields_to_index => {"_id" => true}})
398
+ end
399
+
400
+ @jor.test.insert(create_sample_doc_restaurant({"_id" => 1}),
401
+ {:excluded_fields_to_index => {"description" => true}})
402
+
403
+ @jor.test.insert(create_sample_doc_restaurant({"_id" => 42}),
404
+ {:excluded_fields_to_index => {}})
405
+
406
+ v = []
407
+ @jor.test.indexes(1).each do |ind|
408
+ v << ind["path"]
409
+ end
410
+ assert_equal false, v.include?("/description")
411
+
412
+ v = []
413
+ @jor.test.indexes(42).each do |ind|
414
+ v << ind["path"]
415
+ end
416
+ assert_equal true, v.include?("/description")
417
+
418
+ res = @jor.test.find({},{:reversed => true})
419
+ assert_equal 2, res.size
420
+ assert_equal "very long description that we might not want to index", res.first["description"]
421
+ assert_equal 42, res.first["_id"]
422
+ assert_equal "very long description that we might not want to index", res.last["description"]
423
+ assert_equal 1, res.last["_id"]
424
+
425
+ res = @jor.test.find({"description" => "very long description that we might not want to index"}, :reversed => true)
426
+ assert_equal 1, res.size
427
+ assert_equal 42, res.first["_id"]
428
+
429
+ end
430
+
431
+ def test_auto_increment_collections
432
+ @jor.create_collection("no_auto_increment")
433
+ @jor.create_collection("no_auto_increment2", :auto_increment => false)
434
+ @jor.create_collection("auto_increment",:auto_increment => true)
435
+
436
+ assert_equal false, @jor.no_auto_increment.auto_increment?
437
+ assert_equal false, @jor.no_auto_increment2.auto_increment?
438
+ assert_equal true, @jor.auto_increment.auto_increment?
439
+
440
+ 10.times do |i|
441
+ @jor.auto_increment.insert({"foo" => "bar"})
442
+ end
443
+
444
+ assert_equal 10, @jor.auto_increment.count()
445
+
446
+ assert_raise JOR::DocumentDoesNotNeedId do
447
+ @jor.auto_increment.insert({"_id"=> 10, "foo" => "bar"})
448
+ end
449
+
450
+ assert_equal 10, @jor.auto_increment.count()
451
+ assert_equal 10, @jor.auto_increment.last_id()
452
+ assert_equal 0, @jor.no_auto_increment.last_id()
453
+ end
454
+
455
+ def test_last_id_for_collections
456
+ @jor.create_collection("no_auto_increment")
457
+ @jor.create_collection("auto_increment",:auto_increment => true)
458
+
459
+ assert_equal 0, @jor.no_auto_increment.last_id()
460
+ assert_equal 0, @jor.auto_increment.last_id()
461
+
462
+ 10.times do |i|
463
+ @jor.auto_increment.insert({"foo" => "bar"})
464
+ end
465
+
466
+ assert_equal 10, @jor.auto_increment.last_id()
467
+ assert_not_nil @jor.auto_increment.find({"_id" => 10}).first
468
+
469
+ 10.times do |i|
470
+ @jor.no_auto_increment.insert({"_id" => i+10, "foo" => "bar"})
471
+ end
472
+
473
+ assert_equal 19, @jor.no_auto_increment.last_id()
474
+ assert_not_nil @jor.no_auto_increment.find({"_id" => 10}).first
475
+ end
476
+
477
+ def test_ids_expections_for_collections
478
+ @jor.create_collection("no_auto_increment")
479
+ @jor.create_collection("auto_increment",:auto_increment => true)
480
+
481
+ assert_raise JOR::DocumentDoesNotNeedId do
482
+ @jor.auto_increment.insert({"_id"=> 10, "foo" => "bar"})
483
+ end
484
+
485
+ assert_raise JOR::DocumentNeedsId do
486
+ @jor.no_auto_increment.insert({"foo" => "bar"})
487
+ end
488
+
489
+ assert_raise JOR::InvalidDocumentId do
490
+ @jor.no_auto_increment.insert({"_id"=> "10", "foo" => "bar"})
491
+ end
492
+
493
+ assert_raise JOR::InvalidDocumentId do
494
+ @jor.no_auto_increment.insert({"_id"=> -1, "foo" => "bar"})
495
+ end
496
+ end
497
+
498
+ def test_ids_will_be_sorted
499
+ v = [1, 10, 100, 1000, 10000, 2, 20, 200, 2000, 20000]
500
+ v_sorted = v.sort
501
+ v_shuffled = v.shuffle
502
+
503
+ v_shuffled.each do |val|
504
+ @jor.test.insert({"_id" => val, "foo" => "bar"})
505
+ end
506
+
507
+ res = @jor.test.find({})
508
+ assert_equal v.size, res.size
509
+
510
+ res.each_with_index do |item, i|
511
+ assert_equal v_sorted[i], item["_id"]
512
+ end
513
+ end
514
+
515
+ def test_concurrent_inserts
516
+
517
+ threads = []
518
+ inserted_by_thread = []
519
+ 5.times do |i|
520
+ inserted_by_thread[i] = []
521
+ threads << Thread.new {
522
+ id = i
523
+ 1000.times do |j|
524
+ begin
525
+ doc = @jor.test.insert(create_sample_doc_restaurant({"_id" => j}))
526
+ inserted_by_thread[id] << j unless doc.nil?
527
+ sleep(0.1) if (j%200==0)
528
+ rescue Exception => e
529
+ end
530
+ end
531
+ }
532
+ end
533
+
534
+ threads.each do |t|
535
+ t.join()
536
+ end
537
+
538
+ res = @jor.test.find({},{:max_documents => -1})
539
+ assert_equal 1000, res.size
540
+
541
+ all = inserted_by_thread[0]
542
+ inserted_by_thread.each do |curr|
543
+ all = all & curr
544
+ end
545
+ assert_equal 0, all.size
546
+
547
+ all = inserted_by_thread[0]
548
+ inserted_by_thread.each do |curr|
549
+ all = all | curr
550
+ end
551
+ assert_equal 1000, all.size
552
+ end
553
+
554
+ def test_intervals
555
+ 1000.times do |i|
556
+ @jor.test.insert(create_sample_doc_restaurant({"_id" => i, "at" => i}))
557
+ end
558
+
559
+ docs = @jor.test.find({})
560
+ assert_equal 1000, docs.size
561
+
562
+ docs = @jor.test.find({"at" => {"$lt" => 100}})
563
+ assert_equal 100, docs.size
564
+
565
+ docs = @jor.test.find({"at" => {"$lt" => 100, "$gte" => 50}})
566
+ assert_equal 50, docs.size
567
+
568
+ curr = 50
569
+ docs.each do |doc|
570
+ assert_equal curr, doc["_id"]
571
+ curr+=1
572
+ end
573
+
574
+ docs = @jor.test.find({"at" => {"$lt" => 100, "$gte" => 150}})
575
+ assert_equal 0, docs.size
576
+ end
577
+
578
+ def test_update
579
+ sample_docs = []
580
+ 5.times do |i|
581
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "foo" => "bar", "year" => 2000+i })
582
+ end
583
+
584
+ @jor.test.update({"name" => "foo_4"}, {"name" => "foo_changed_4", "additional_field" => 3})
585
+
586
+ docs = @jor.test.find({"name" => "foo_4"})
587
+ assert_equal 0, docs.size()
588
+
589
+ [{"additional_field" => 3}, {"name" => "foo_changed_4"}, {"year" => 2004}].each do |search_doc|
590
+ docs = @jor.test.find(search_doc)
591
+ assert_equal 1, docs.size()
592
+ assert_equal "foo_changed_4", docs.first["name"]
593
+ assert_equal 3, docs.first["additional_field"]
594
+ assert_equal 2004, docs.first["year"]
595
+ assert_equal "bar", docs.first["foo"]
596
+ end
597
+
598
+ end
599
+
600
+ def test_update_with_id
601
+ sample_docs = []
602
+ 5.times do |i|
603
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "foo" => "bar", "year" => 2000+i })
604
+ end
605
+
606
+ docs = @jor.test.update({"name" => "foo_4"}, {"name" => "foo_changed_4", "additional_field" => 3, "_id" => 666})
607
+ assert_equal 1, docs.size()
608
+ assert_equal "foo_changed_4", docs.first["name"]
609
+ assert_equal 4, docs.first["_id"]
610
+
611
+ docs = @jor.test.find({"_id" => 4})
612
+ assert_equal 1, docs.size()
613
+ assert_equal "foo_changed_4", docs.first["name"]
614
+ assert_equal 4, docs.first["_id"]
615
+ end
616
+
617
+ def test_update_with_excluded_fields
618
+ sample_docs = []
619
+ 5.times do |i|
620
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "foo" => "bar", "year" => 2000+i })
621
+ end
622
+
623
+ docs = @jor.test.update({"foo" => "bar"}, {"foo" => "bar_changed", "description" => "long ass description"},
624
+ {:excluded_fields_to_index => {"description" => true}})
625
+
626
+ assert_equal 5, docs.size()
627
+ assert_equal "long ass description", docs.first["description"]
628
+ assert_equal "long ass description", docs.last["description"]
629
+
630
+ docs = @jor.test.find({"foo" => "bar_changed"})
631
+ assert_equal 5, docs.size()
632
+ assert_equal "long ass description", docs.first["description"]
633
+ assert_equal "long ass description", docs.last["description"]
634
+
635
+ docs = @jor.test.find({"description" => "long ass description"})
636
+ assert_equal 0, docs.size()
637
+
638
+ docs = @jor.test.update({"foo" => "bar_changed"}, {"description" => "long ass description"})
639
+ assert_equal 5, docs.size()
640
+
641
+ docs = @jor.test.find({"description" => "long ass description"})
642
+ assert_equal 5, docs.size()
643
+ end
644
+
645
+ def test_update_massive_update
646
+
647
+ sample_docs = []
648
+ 5.times do |i|
649
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "foo" => "bar", "year" => 2000+i })
650
+ end
651
+
652
+ docs = @jor.test.find({"foo" => "bar"})
653
+ assert_equal 5, docs.size()
654
+
655
+ docs = @jor.test.find({"foo" => "bar_changed"})
656
+ assert_equal 0, docs.size()
657
+
658
+ docs = @jor.test.find({"bar" => "bar_added"})
659
+ assert_equal 0, docs.size()
660
+
661
+ @jor.test.update({"foo" => "bar"}, {"foo" => "bar_changed", "bar" => "bar_added"})
662
+
663
+ docs = @jor.test.find({"foo" => "bar"})
664
+ assert_equal 0, docs.size()
665
+
666
+ docs = @jor.test.find({"foo" => "bar_changed"})
667
+ assert_equal 5, docs.size()
668
+
669
+ docs = @jor.test.find({"bar" => "bar_added"})
670
+ assert_equal 5, docs.size()
671
+ end
672
+
673
+ def test_update_remove_field
674
+
675
+ sample_docs = []
676
+ 5.times do |i|
677
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "foo" => "bar", "year" => 2000+i })
678
+ end
679
+
680
+ @jor.test.update({"foo" => "bar"}, {"foo" => nil, "xtra" => "large"})
681
+
682
+ docs = @jor.test.find({"foo" => "bar"})
683
+ assert_equal 0, docs.size()
684
+
685
+ docs = @jor.test.find({})
686
+ assert_equal 5, docs.size()
687
+
688
+ docs.each_with_index do |d, i|
689
+ assert_equal "foo_#{i}", d["name"]
690
+ assert_equal i, d["_id"]
691
+ assert_equal nil, d["foo"]
692
+ assert_equal "large", d["xtra"]
693
+ end
694
+
695
+ @jor.test.update({"xtra" => "large"}, {"foo" => "bar"})
696
+
697
+ docs = @jor.test.find({"foo" => "bar"})
698
+ assert_equal 5, docs.size()
699
+
700
+ docs.each_with_index do |d, i|
701
+ assert_equal "foo_#{i}", d["name"]
702
+ assert_equal i, d["_id"]
703
+ assert_equal "bar", d["foo"]
704
+ assert_equal "large", d["xtra"]
705
+ end
706
+
707
+ end
708
+
709
+ def test_update_remove_filed_nested
710
+
711
+ @jor.test.insert(create_sample_doc_restaurant({"_id" => 42}))
712
+ docs = @jor.test.find({"address" => {"zipcode" => "08104"}})
713
+ assert_equal 1, docs.size()
714
+
715
+ indexes_before = @jor.test.indexes(42)
716
+
717
+ @jor.test.update({"_id" => 42}, {"address" => {"zipcode" => nil}})
718
+ docs = @jor.test.find({"address" => {"zipcode" => "08104"}})
719
+ assert_equal 0, docs.size
720
+
721
+ indexes_after = @jor.test.indexes(42)
722
+ ## -1 because we removed address/zipcode, but plus 1 because now _updated_at exists
723
+ assert_equal indexes_before.size, indexes_after.size
724
+ indexes_after.each do |item|
725
+ assert_equal false, ["/address/zipcode"].include?(item["path"])
726
+ end
727
+
728
+
729
+ docs = @jor.test.find({"_id" => 42})
730
+ assert_equal 1, docs.size
731
+ assert_equal "Ann Arbor", docs.first["address"]["city"]
732
+ assert_equal "Main St 100", docs.first["address"]["address"]
733
+
734
+ @jor.test.update({"_id" => 42}, {"address" => nil})
735
+ docs = @jor.test.find({"address" => {"zipcode" => "08104"}})
736
+ assert_equal 0, docs.size
737
+
738
+ indexes_after = @jor.test.indexes(42)
739
+ assert_equal indexes_before.size - 2, indexes_after.size
740
+
741
+ indexes_after.each do |item|
742
+ assert_equal false, ["/address/zipcode", "/address/address", "/address/city"].include?(item["path"])
743
+ end
744
+
745
+ end
746
+
747
+ def test_update_arrays
748
+
749
+ sample_docs = []
750
+ 5.times do |i|
751
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "foo" => [1,2,3,4,5], "year" => 2000+i })
752
+ end
753
+
754
+ @jor.test.update({"_id" => 4}, {"foo" => [6,7,8]})
755
+ docs = @jor.test.find({"_id" => 4})
756
+ assert_equal 1, docs.size()
757
+ assert_equal [6,7,8].sort, docs.first["foo"].sort
758
+
759
+ @jor.test.update({"_id" => 4}, {"foo" => {"bar" => [9, 10]}})
760
+ docs = @jor.test.find({"_id" => 4})
761
+ assert_equal 1, docs.size()
762
+ assert_equal [9, 10].sort, docs.first["foo"]["bar"].sort
763
+
764
+ @jor.test.update({"_id" => 4}, {"foo" => {"bar" => [11, 12]}})
765
+ docs = @jor.test.find({"_id" => 4})
766
+ assert_equal 1, docs.size()
767
+ assert_equal [11, 12].sort, docs.first["foo"]["bar"].sort
768
+
769
+ @jor.test.update({"_id" => 4}, {"foo" => nil})
770
+ docs = @jor.test.find({"_id" => 4})
771
+ assert_equal 1, docs.size()
772
+ assert_equal nil, docs.first["foo"]
773
+
774
+ assert_equal 0, ([{"path"=>"/name", "obj"=>"String", "value"=>"foo_4"},
775
+ {"path"=>"/_id", "obj"=>"Numeric", "value"=>"4"},
776
+ {"path"=>"/year", "obj"=>"Numeric", "value"=>"2004"}] - @jor.test.indexes(4)).size
777
+
778
+
779
+ end
780
+
781
+ def test_created_and_update_at
782
+ start_time = Time.now.to_f
783
+ sample_docs = []
784
+ 5.times do |i|
785
+ sample_docs << @jor.test.insert({"_id" => i, "name" => "foo_#{i}", "foo" => [1,2,3,4,5], "year" => 2000+i })
786
+ end
787
+ end_time = Time.now.to_f
788
+
789
+ sample_docs.each do |d|
790
+ assert_equal true, d["_created_at"]>=start_time && d["_created_at"]<=end_time
791
+ end
792
+
793
+ docs = @jor.test.find({})
794
+ docs.each do |d|
795
+ assert_equal true, d["_created_at"]>=start_time && d["_created_at"]<=end_time
796
+ assert_equal nil, d["_updated_at"]
797
+ end
798
+
799
+ @jor.test.insert({"_id" => 42, "name" => "foo_#{42}", "foo" => [1,2,3,4,5], "year" => 2000+42, "_created_at" => start_time})
800
+ docs = @jor.test.find({"_id" => 42})
801
+ assert_equal start_time, docs.first["_created_at"]
802
+
803
+ start_time2 = Time.now.to_f
804
+ @jor.test.update({},{"updated" => "yeah"})
805
+ end_time2 = Time.now.to_f
806
+
807
+ docs = @jor.test.find({})
808
+ docs.each do |d|
809
+ assert_equal true, d["_created_at"]>=start_time && d["_created_at"]<=end_time
810
+ assert_equal true, d["_updated_at"]>=start_time2 && d["_updated_at"]<=end_time2
811
+ end
812
+
813
+ assert_equal 6, docs.size()
814
+
815
+ @jor.test.delete({"_created_at" => {"$lte" => start_time}})
816
+ docs = @jor.test.find({})
817
+ assert_equal 5, docs.size()
818
+ end
819
+
820
+ def test_boolean_fields
821
+
822
+ doc = @jor.test.insert({"_id" => 1, "foo" => "bar", "is_true" => true, "is_false" => false})
823
+ assert_equal true, doc["is_true"]
824
+ assert_equal false, doc["is_false"]
825
+
826
+ doc = @jor.test.insert({"_id" => 2, "foo" => "bar", "is_true" => true, "is_false" => false})
827
+ assert_equal true, doc["is_true"]
828
+ assert_equal false, doc["is_false"]
829
+
830
+ docs = @jor.test.find({})
831
+ assert_equal 2, docs.size
832
+ assert_equal true, docs.first["is_true"]
833
+ assert_equal false, docs.first["is_false"]
834
+ assert_equal true, docs.last["is_true"]
835
+ assert_equal false, docs.last["is_false"]
836
+
837
+ docs = @jor.test.find({"_id" => 2, "is_true" => true})
838
+ assert_equal 1, docs.size
839
+ assert_equal 2, docs.first["_id"]
840
+ assert_equal true, docs.first["is_true"]
841
+ assert_equal false, docs.first["is_false"]
842
+
843
+ docs = @jor.test.find({"_id" => 2, "foo" => "not_bar"})
844
+ assert_equal 0, docs.size
845
+
846
+ docs = @jor.test.find({"is_false" => false})
847
+ assert_equal 2, docs.size
848
+
849
+ docs = @jor.test.find({"_id" => 2, "is_true" => false})
850
+ assert_equal 0, docs.size
851
+
852
+ docs = @jor.test.find({"_id" => 2, "is_true" => "false"})
853
+ assert_equal 0, docs.size
854
+
855
+ docs = @jor.test.find({"_id" => 2, "is_true" => "true"})
856
+ assert_equal 0, docs.size
857
+
858
+ docs = @jor.test.find({"_id" => 2, "is_true" => nil})
859
+ assert_equal 0, docs.size
860
+
861
+ docs = @jor.test.update({"_id" => 2, "is_true" => true}, {"is_true" => false})
862
+ assert_equal 1, docs.size
863
+ assert_equal false, docs.first["is_true"]
864
+
865
+ docs = @jor.test.find({"_id" => 2})
866
+ assert_equal 1, docs.size
867
+ assert_equal 2, docs.first["_id"]
868
+ assert_equal false, docs.first["is_true"]
869
+ assert_equal false, docs.first["is_false"]
870
+
871
+ docs = @jor.test.find({"is_true" => {"$in" => [true, false]}})
872
+ assert_equal 2, docs.size
873
+ assert_equal true, docs.first["is_true"]
874
+ assert_equal false, docs.first["is_false"]
875
+ assert_equal 1, docs.first["_id"]
876
+ assert_equal false, docs.last["is_true"]
877
+ assert_equal false, docs.last["is_false"]
878
+ assert_equal 2, docs.last["_id"]
879
+
880
+ docs = @jor.test.find({"is_true" => {"$all" => [true, false]}})
881
+ assert_equal 0, docs.size
882
+ end
883
+
884
+ end