marklogic 0.0.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.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +10 -0
  3. data/.gitignore +15 -0
  4. data/.rspec +2 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/Gemfile +17 -0
  8. data/Guardfile +45 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +31 -0
  11. data/Rakefile +6 -0
  12. data/lib/marklogic.rb +21 -0
  13. data/lib/marklogic/app_server.rb +60 -0
  14. data/lib/marklogic/application.rb +244 -0
  15. data/lib/marklogic/collection.rb +265 -0
  16. data/lib/marklogic/connection.rb +308 -0
  17. data/lib/marklogic/consts.rb +35 -0
  18. data/lib/marklogic/cursor.rb +238 -0
  19. data/lib/marklogic/database.rb +205 -0
  20. data/lib/marklogic/database_settings.rb +13 -0
  21. data/lib/marklogic/database_settings/element_word_lexicon.rb +28 -0
  22. data/lib/marklogic/database_settings/geospatial_element_child_index.rb +41 -0
  23. data/lib/marklogic/database_settings/geospatial_element_index.rb +38 -0
  24. data/lib/marklogic/database_settings/geospatial_element_pair_index.rb +42 -0
  25. data/lib/marklogic/database_settings/geospatial_path_index.rb +37 -0
  26. data/lib/marklogic/database_settings/index.rb +27 -0
  27. data/lib/marklogic/database_settings/range_element_index.rb +77 -0
  28. data/lib/marklogic/database_settings/range_field_index.rb +37 -0
  29. data/lib/marklogic/database_settings/range_path_index.rb +37 -0
  30. data/lib/marklogic/exceptions.rb +5 -0
  31. data/lib/marklogic/forest.rb +47 -0
  32. data/lib/marklogic/loggable.rb +46 -0
  33. data/lib/marklogic/object_id.rb +46 -0
  34. data/lib/marklogic/persistence.rb +29 -0
  35. data/lib/marklogic/queries.rb +18 -0
  36. data/lib/marklogic/queries/and_not_query.rb +14 -0
  37. data/lib/marklogic/queries/and_query.rb +14 -0
  38. data/lib/marklogic/queries/base_query.rb +40 -0
  39. data/lib/marklogic/queries/boost_query.rb +14 -0
  40. data/lib/marklogic/queries/collection_query.rb +14 -0
  41. data/lib/marklogic/queries/container_query.rb +15 -0
  42. data/lib/marklogic/queries/directory_query.rb +20 -0
  43. data/lib/marklogic/queries/document_fragment_query.rb +13 -0
  44. data/lib/marklogic/queries/document_query.rb +14 -0
  45. data/lib/marklogic/queries/geospatial_query.rb +44 -0
  46. data/lib/marklogic/queries/locks_fragment_query.rb +13 -0
  47. data/lib/marklogic/queries/near_query.rb +31 -0
  48. data/lib/marklogic/queries/not_in_query.rb +14 -0
  49. data/lib/marklogic/queries/not_query.rb +13 -0
  50. data/lib/marklogic/queries/or_query.rb +24 -0
  51. data/lib/marklogic/queries/properties_fragment_query.rb +13 -0
  52. data/lib/marklogic/queries/range_query.rb +67 -0
  53. data/lib/marklogic/queries/value_query.rb +44 -0
  54. data/lib/marklogic/queries/word_query.rb +38 -0
  55. data/lib/marklogic/version.rb +3 -0
  56. data/marklogic.gemspec +23 -0
  57. data/spec/marklogic/app_server_spec.rb +21 -0
  58. data/spec/marklogic/application_spec.rb +105 -0
  59. data/spec/marklogic/collection_spec.rb +154 -0
  60. data/spec/marklogic/connection_spec.rb +128 -0
  61. data/spec/marklogic/cursor_spec.rb +219 -0
  62. data/spec/marklogic/database_settings/element_word_lexicon_spec.rb +21 -0
  63. data/spec/marklogic/database_settings/geospatial_element_child_index_spec.rb +26 -0
  64. data/spec/marklogic/database_settings/geospatial_element_index_spec.rb +24 -0
  65. data/spec/marklogic/database_settings/geospatial_element_pair_index_spec.rb +27 -0
  66. data/spec/marklogic/database_settings/geospatial_path_index_spec.rb +23 -0
  67. data/spec/marklogic/database_settings/range_element_index_spec.rb +34 -0
  68. data/spec/marklogic/database_settings/range_field_index_spec.rb +23 -0
  69. data/spec/marklogic/database_settings/range_path_index_spec.rb +23 -0
  70. data/spec/marklogic/database_spec.rb +108 -0
  71. data/spec/marklogic/forest_spec.rb +30 -0
  72. data/spec/marklogic/queries/and_not_query_spec.rb +13 -0
  73. data/spec/marklogic/queries/and_query_spec.rb +31 -0
  74. data/spec/marklogic/queries/boost_query_spec.rb +13 -0
  75. data/spec/marklogic/queries/collection_query_spec.rb +16 -0
  76. data/spec/marklogic/queries/container_query_spec.rb +11 -0
  77. data/spec/marklogic/queries/directory_query_spec.rb +21 -0
  78. data/spec/marklogic/queries/document_fragment_query_spec.rb +11 -0
  79. data/spec/marklogic/queries/document_query_spec.rb +16 -0
  80. data/spec/marklogic/queries/locks_fragement_query_spec.rb +11 -0
  81. data/spec/marklogic/queries/near_query_spec.rb +62 -0
  82. data/spec/marklogic/queries/not_in_query_spec.rb +13 -0
  83. data/spec/marklogic/queries/not_query_spec.rb +11 -0
  84. data/spec/marklogic/queries/or_query_spec.rb +32 -0
  85. data/spec/marklogic/queries/properties_fragment_query_spec.rb +11 -0
  86. data/spec/marklogic/queries/range_query_spec.rb +71 -0
  87. data/spec/marklogic/queries/value_query_spec.rb +68 -0
  88. data/spec/marklogic/queries/word_query_spec.rb +53 -0
  89. data/spec/spec_helper.rb +68 -0
  90. metadata +186 -0
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe MarkLogic::Connection do
4
+
5
+ class Response
6
+
7
+ def initialize(b)
8
+ @body = b
9
+ end
10
+
11
+ def body
12
+ @body
13
+ end
14
+
15
+ def body=(val)
16
+ @body = val
17
+ end
18
+
19
+ def read_body
20
+ true
21
+ end
22
+
23
+ def [](x)
24
+ "multipart/mixed; boundary=4ae338aa9d1fc38e"
25
+ end
26
+ end
27
+
28
+ before do
29
+ @b = MarkLogic::Connection.app_services_connection
30
+ end
31
+
32
+ describe "split_multipart" do
33
+ it "should split properly when multiple values are returned" do
34
+ response = Response.new(%Q{\r\n--4ae338aa9d1fc38e\r\nContent-Type: text/plain\r\nX-Primitive: integer\r\n\r\n5\r\n--4ae338aa9d1fc38e\r\nContent-Type: text/plain\r\nX-Primitive: integer\r\n\r\n6\r\n--4ae338aa9d1fc38e--\r\n})
35
+ expect(@b.send(:split_multipart, response)).to eq([5, 6])
36
+ end
37
+
38
+ it "should split properly when a single value is returned" do
39
+ response = Response.new(%Q{\r\n--4ae338aa9d1fc38e\r\nContent-Type: text/plain\r\nX-Primitive: integer\r\n\r\n5\r\n--4ae338aa9d1fc38e--\r\n})
40
+ expect(@b.send(:split_multipart, response)).to eq(5)
41
+ end
42
+
43
+ it "should split properly when an array value is returned" do
44
+ response = Response.new(%Q{\r\n--4ae338aa9d1fc38e\r\nContent-Type: application/json\r\nX-Primitive: array\r\n\r\n["5", 6]\r\n--4ae338aa9d1fc38e--\r\n})
45
+ expect(@b.send(:split_multipart, response)).to eq(["5", 6])
46
+ end
47
+
48
+ it "should split properly when an object value is returned" do
49
+ response = Response.new(%Q{\r\n--4ae338aa9d1fc38e\r\nContent-Type: application/json\r\nX-Primitive: map\r\n\r\n{"hi":"stuff"}\r\n--4ae338aa9d1fc38e--\r\n})
50
+ expect(@b.send(:split_multipart, response)).to eq({"hi" => "stuff"})
51
+ end
52
+
53
+ it "should split properly when a true boolean is returned" do
54
+ response = Response.new(%Q{\r\n--4ae338aa9d1fc38e\r\nContent-Type: text/plain\r\nX-Primitive: boolean\r\n\r\ntrue\r\n--4ae338aa9d1fc38e--\r\n})
55
+ expect(@b.send(:split_multipart, response)).to be true
56
+ end
57
+
58
+ it "should split properly when a false boolean is returned" do
59
+ response = Response.new(%Q{\r\n--4ae338aa9d1fc38e\r\nContent-Type: text/plain\r\nX-Primitive: boolean\r\n\r\nfalse\r\n--4ae338aa9d1fc38e--\r\n})
60
+ expect(@b.send(:split_multipart, response)).to be false
61
+ end
62
+
63
+ it "should split properly when a decimal is returned" do
64
+ response = Response.new(%Q{\r\n--4ae338aa9d1fc38e\r\nContent-Type: text/plain\r\nX-Primitive: decimal\r\n\r\n3.1\r\n--4ae338aa9d1fc38e--\r\n})
65
+ expect(@b.send(:split_multipart, response)).to eq(3.1)
66
+ end
67
+
68
+ it "should split properly when a crazy object is returned" do
69
+ response = Response.new(%Q{\r\n--4ae338aa9d1fc38e\r\nContent-Type: application/json\r\nX-Primitive: map\r\n\r\n{"stuff":[1, 2, 3], "junk":false}\r\n--4ae338aa9d1fc38e--\r\n})
70
+ expect(@b.send(:split_multipart, response)).to eq({"stuff" => [1, 2, 3], "junk" => false})
71
+ end
72
+
73
+ end
74
+
75
+ describe "run_query" do
76
+ it "should split properly when multiple values are returned" do
77
+ expect(@b.run_query('(5, 6)', 'xquery').body).to eq([5, 6])
78
+ end
79
+
80
+ it "should split properly when a single value is returned" do
81
+ expect(@b.run_query('5').body).to eq(5)
82
+ end
83
+
84
+ it "should split properly when an array value is returned" do
85
+ expect(@b.run_query(%Q{x = ["5", 6]; x}).body).to eq(["5", 6])
86
+ end
87
+
88
+ it "should split properly when an object value is returned" do
89
+ expect(@b.run_query('x = {hi: "stuff"}; x').body).to eq({"hi" => "stuff"})
90
+ end
91
+
92
+ it "should split properly when a true boolean is returned" do
93
+ expect(@b.run_query('true').body).to be true
94
+ end
95
+
96
+ it "should split properly when a false boolean is returned" do
97
+ expect(@b.run_query('false').body).to be false
98
+ end
99
+
100
+ it "should split properly when a decimal is returned" do
101
+ expect(@b.run_query('3.1').body).to eq(3.1)
102
+ end
103
+
104
+ it "should split properly when a crazy object is returned" do
105
+ expect(@b.run_query(%Q{x = { stuff: [1, 2, 3], junk: false}; x}).body).to eq({"stuff" => [1, 2, 3], "junk" => false})
106
+ end
107
+ end
108
+
109
+ describe "#digest" do
110
+ it "#digest should cache login creds" do
111
+ expect(@b.run_query('(5, 6)', 'xquery').body).to eq([5, 6])
112
+ expect(@b.run_query('(5, 6)', 'xquery').body).to eq([5, 6])
113
+ expect(@b.run_query('(5, 6)', 'xquery').body).to eq([5, 6])
114
+ expect(@b.run_query('(5, 6)', 'xquery').body).to eq([5, 6])
115
+ end
116
+ end
117
+
118
+ describe "run_query" do
119
+ it "should work" do
120
+ expect(@b.run_query('(5, 6)', 'xquery').body).to eq([5, 6])
121
+ expect(@b.run_query('<a/>,<a/>', 'xquery').body).to eq(['<a/>', '<a/>'])
122
+
123
+ res = @b.run_query('<a/>, try { fn:error((), "stuff") } catch($ex) { $ex }', 'xquery').body
124
+ expect(res[0]).to eq('<a/>')
125
+ expect(res[1]).to match(/<error:error.*/)
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,219 @@
1
+ require 'spec_helper'
2
+
3
+ describe MarkLogic::Cursor do
4
+ before do
5
+ @collection = @database.collection("stuff")
6
+ @collection.drop
7
+
8
+ @collection.save((1..101).map do |n|
9
+ {:_id => n, :name => "John#{n}", :age => n, :weight => n % 5, :stuff => "junk"}
10
+ end)
11
+ end
12
+
13
+ describe "#sort" do
14
+ it "should sort ascending" do
15
+ c = MarkLogic::Cursor.new(@collection, {
16
+ :sort => [['age', 1]]
17
+ })
18
+ expect(c.count).to eq 101
19
+ expect(c.first['age']).to eq(1)
20
+ end
21
+
22
+ it "should sort descending" do
23
+ c = MarkLogic::Cursor.new(@collection, {
24
+ :sort => [['age', -1]]
25
+ })
26
+ expect(c.count).to eq 101
27
+ expect(c.first['age']).to eq(101)
28
+ end
29
+
30
+ it "should do multiple sorts asc, desc" do
31
+ options = {
32
+ :sort => [['weight', 1], ['age', -1]]
33
+ }
34
+ c = MarkLogic::Cursor.new(@collection, options)
35
+ expect(c.count).to eq 101
36
+ first = c.first
37
+ expect(first['age']).to eq(100)
38
+ expect(first['weight']).to eq(0)
39
+ end
40
+
41
+ it "should do multiple sorts asc, asc" do
42
+ options = {
43
+ :sort => [['weight', 1], ['age', 1]]
44
+ }
45
+ c = MarkLogic::Cursor.new(@collection, options)
46
+ expect(c.count).to eq 101
47
+ first = c.first
48
+ expect(first['age']).to eq(5)
49
+ expect(first['weight']).to eq(0)
50
+ end
51
+
52
+ it "should do multiple sorts desc, asc" do
53
+ options = {
54
+ :sort => [['weight', -1], ['age', 1]]
55
+ }
56
+ c = MarkLogic::Cursor.new(@collection, options)
57
+ expect(c.count).to eq 101
58
+ first = c.first
59
+ expect(first['age']).to eq(4)
60
+ expect(first['weight']).to eq(4)
61
+ end
62
+
63
+ it "should do multiple sorts desc, asc" do
64
+ options = {
65
+ :sort => [['weight', -1], ['age', -1]]
66
+ }
67
+ c = MarkLogic::Cursor.new(@collection, options)
68
+ expect(c.count).to eq 101
69
+ first = c.first
70
+ expect(first['age']).to eq(99)
71
+ expect(first['weight']).to eq(4)
72
+ end
73
+ end
74
+
75
+ describe "#operators" do
76
+ it "should support EQ" do
77
+ criteria = { 'age' => { '$eq' => 3 } }
78
+ options = {
79
+ :query => @collection.from_criteria(criteria)
80
+ }
81
+ c = MarkLogic::Cursor.new(@collection, options)
82
+ expect(c.count).to eq 1
83
+ expect(c.first['age']).to eq 3
84
+
85
+ criteria = { 'age' => 3 }
86
+ options = {
87
+ :query => @collection.from_criteria(criteria)
88
+ }
89
+ c = MarkLogic::Cursor.new(@collection, options)
90
+ expect(c.count).to eq 1
91
+ expect(c.first['age']).to eq 3
92
+
93
+ criteria = { 'age' => (1..100).to_a }
94
+ c = MarkLogic::Cursor.new(@collection, {
95
+ :query => @collection.from_criteria(criteria)
96
+ })
97
+ expect(c.count).to eq 100
98
+ end
99
+
100
+ it "should support LT" do
101
+ criteria = { 'age' => { '$lt' => 3 } }
102
+ c = MarkLogic::Cursor.new(@collection, {
103
+ :query => @collection.from_criteria(criteria)
104
+ })
105
+ expect(c.count).to eq 2
106
+ expect([1, 2].include?(c.first['age'])).to be true
107
+ expect([1, 2].include?(c.next['age'])).to be true
108
+ end
109
+
110
+ it "should support GT" do
111
+ criteria = { 'age' => { '$gt' => 99 } }
112
+ c = MarkLogic::Cursor.new(@collection, {
113
+ :query => @collection.from_criteria(criteria)
114
+ })
115
+ expect(c.count).to eq 2
116
+ expect([100, 101].include?(c.first['age'])).to be true
117
+ expect([100, 101].include?(c.next['age'])).to be true
118
+ end
119
+
120
+ it "should support LE" do
121
+ criteria = { 'age' => { '$le' => 2 } }
122
+ c = MarkLogic::Cursor.new(@collection, {
123
+ :query => @collection.from_criteria(criteria)
124
+ })
125
+ expect(c.count).to eq 2
126
+ expect([1, 2].include?(c.first['age'])).to be true
127
+ expect([1, 2].include?(c.next['age'])).to be true
128
+ end
129
+
130
+ it "should support GE" do
131
+ criteria = { 'age' => { '$ge' => 100 } }
132
+ c = MarkLogic::Cursor.new(@collection, {
133
+ :query => @collection.from_criteria(criteria)
134
+ })
135
+ expect(c.count).to eq 2
136
+ expect([100, 101].include?(c.first['age'])).to be true
137
+ expect([100, 101].include?(c.next['age'])).to be true
138
+ end
139
+
140
+ it "should support NE" do
141
+ criteria = { 'age' => { '$ne' => 100 } }
142
+ c = MarkLogic::Cursor.new(@collection, {
143
+ :query => @collection.from_criteria(criteria)
144
+ })
145
+ expect(c.count).to eq 100
146
+ end
147
+ end
148
+
149
+ describe "count" do
150
+ it "should work when indexes are provided" do
151
+ criteria = { 'age' => { '$gt' => 3 } }
152
+ c = MarkLogic::Cursor.new(@collection, {
153
+ :query => @collection.from_criteria(criteria)
154
+ })
155
+ expect(c.count).to eq 98
156
+ end
157
+
158
+ it "should fail when no indexes are provided and should be" do
159
+ criteria = { 'stuff' => { '$gt' => 3 } }
160
+ expect {@collection.from_criteria(criteria) }.to raise_error(MarkLogic::MissingIndexError)
161
+ end
162
+
163
+ it "should return the correct count" do
164
+ c = MarkLogic::Cursor.new(@collection)
165
+ expect(c.count).to eq 101
166
+ end
167
+ end
168
+
169
+ describe "each" do
170
+ it "should work when indexes are provided" do
171
+ criteria = { 'age' => { '$gt' => 3 } }
172
+ c = MarkLogic::Cursor.new(@collection, {
173
+ :query => @collection.from_criteria(criteria)
174
+ })
175
+
176
+ count = 0
177
+ c.each do |doc|
178
+ count = count + 1
179
+ expect(doc.kind_of?(Hash)).to eq true
180
+ end
181
+ expect(count).to eq 98
182
+ end
183
+
184
+ it "should transform results when a transformer is provided" do
185
+ @user_class = Struct.new(:id, :name, :age, :stuff)
186
+
187
+ criteria = { 'age' => { '$gt' => 3 } }
188
+ c = MarkLogic::Cursor.new(@collection, {
189
+ :query => @collection.from_criteria(criteria),
190
+ :transformer => lambda { |doc| @user_class.new(doc['_id'], doc['name'], doc['age'], doc['stuff']) }
191
+ })
192
+
193
+ count = 0
194
+ c.each do |doc|
195
+ count = count + 1
196
+ expect(doc.kind_of?(@user_class)).to be true
197
+ expect(doc.stuff).to eq("junk")
198
+ end
199
+ expect(count).to eq 98
200
+ end
201
+
202
+ # it "should fail when no indexes are provided and should be" do
203
+ # criteria = { 'age' => { '$gt' => 3 } }
204
+ # c = MarkLogic::Cursor.new(@collection, {
205
+ # :query => @collection.from_criteria(criteria)
206
+ # })
207
+ # expect { c.each { |doc| doc } }.to raise_error(MarkLogic::MissingIndexError)
208
+ # end
209
+
210
+ it "should return the correct count" do
211
+ c = MarkLogic::Cursor.new(@collection)
212
+ count = 0
213
+ c.each do |doc|
214
+ count = count + 1
215
+ end
216
+ expect(count).to eq 101
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe MarkLogic::DatabaseSettings::ElementWordLexicon do
4
+ let(:index) do
5
+ MarkLogic::DatabaseSettings::ElementWordLexicon.new("element")
6
+ end
7
+
8
+ context "#new" do
9
+ it "should populate correctly" do
10
+ expect(index.to_json).to eq(
11
+ {
12
+ "element-word-lexicon" => {
13
+ "namespace-uri" => "",
14
+ "localname" => "element",
15
+ "collation" => MarkLogic::DEFAULT_COLLATION
16
+ }
17
+ }
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe MarkLogic::DatabaseSettings::GeospatialElementChildIndex do
4
+ let(:index) do
5
+ MarkLogic::DatabaseSettings::GeospatialElementChildIndex.new("parent", "child")
6
+ end
7
+
8
+ describe "new" do
9
+ it "should populate correctly" do
10
+ expect(index.to_json).to eq(
11
+ {
12
+ "geospatial-element-child-index" => {
13
+ "parent-namespace-uri" => "",
14
+ "parent-localname" => "parent",
15
+ "namespace-uri" => "",
16
+ "localname" => "child",
17
+ "coordinate-system" => "wgs84",
18
+ "point-format" => "point",
19
+ "range-value-positions" => false,
20
+ "invalid-values" => "reject"
21
+ }
22
+ }
23
+ )
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe MarkLogic::DatabaseSettings::GeospatialElementIndex do
4
+ let(:index) do
5
+ MarkLogic::DatabaseSettings::GeospatialElementIndex.new("element")
6
+ end
7
+
8
+ describe "new" do
9
+ it "should populate correctly" do
10
+ expect(index.to_json).to eq(
11
+ {
12
+ "geospatial-element-index" => {
13
+ "namespace-uri" => "",
14
+ "localname" => "element",
15
+ "coordinate-system" => "wgs84",
16
+ "point-format" => "point",
17
+ "range-value-positions" => false,
18
+ "invalid-values" => "reject"
19
+ }
20
+ }
21
+ )
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe MarkLogic::DatabaseSettings::GeospatialElementPairIndex do
4
+ let(:index) do
5
+ MarkLogic::DatabaseSettings::GeospatialElementPairIndex.new("parent", "lat", "lon")
6
+ end
7
+
8
+ describe "new" do
9
+ it "should populate correctly" do
10
+ expect(index.to_json).to eq(
11
+ {
12
+ "geospatial-element-pair-index" => {
13
+ "parent-namespace-uri" => "",
14
+ "parent-localname" => "parent",
15
+ "latitude-namespace-uri" => "",
16
+ "latitude-localname" => "lat",
17
+ "longitude-namespace-uri" => "",
18
+ "longitude-localname" => "lon",
19
+ "coordinate-system" => "wgs84",
20
+ "range-value-positions" => false,
21
+ "invalid-values" => "reject"
22
+ }
23
+ }
24
+ )
25
+ end
26
+ end
27
+ end