libcouchbase-mapo 1.4.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 (104) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +38 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +24 -0
  8. data/README.md +445 -0
  9. data/Rakefile +76 -0
  10. data/ext/README.md +6 -0
  11. data/ext/Rakefile +19 -0
  12. data/lib/libcouchbase.rb +40 -0
  13. data/lib/libcouchbase/bucket.rb +825 -0
  14. data/lib/libcouchbase/callbacks.rb +69 -0
  15. data/lib/libcouchbase/connection.rb +886 -0
  16. data/lib/libcouchbase/design_docs.rb +92 -0
  17. data/lib/libcouchbase/error.rb +68 -0
  18. data/lib/libcouchbase/ext/libcouchbase.rb +1175 -0
  19. data/lib/libcouchbase/ext/libcouchbase/cmdbase.rb +23 -0
  20. data/lib/libcouchbase/ext/libcouchbase/cmdcounter.rb +36 -0
  21. data/lib/libcouchbase/ext/libcouchbase/cmdendure.rb +26 -0
  22. data/lib/libcouchbase/ext/libcouchbase/cmdfts.rb +24 -0
  23. data/lib/libcouchbase/ext/libcouchbase/cmdget.rb +30 -0
  24. data/lib/libcouchbase/ext/libcouchbase/cmdgetreplica.rb +49 -0
  25. data/lib/libcouchbase/ext/libcouchbase/cmdhttp.rb +58 -0
  26. data/lib/libcouchbase/ext/libcouchbase/cmdn1ql.rb +40 -0
  27. data/lib/libcouchbase/ext/libcouchbase/cmdobseqno.rb +33 -0
  28. data/lib/libcouchbase/ext/libcouchbase/cmdobserve.rb +30 -0
  29. data/lib/libcouchbase/ext/libcouchbase/cmdstore.rb +40 -0
  30. data/lib/libcouchbase/ext/libcouchbase/cmdstoredur.rb +45 -0
  31. data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +61 -0
  32. data/lib/libcouchbase/ext/libcouchbase/cmdverbosity.rb +29 -0
  33. data/lib/libcouchbase/ext/libcouchbase/cmdviewquery.rb +61 -0
  34. data/lib/libcouchbase/ext/libcouchbase/contigbuf.rb +14 -0
  35. data/lib/libcouchbase/ext/libcouchbase/create_st.rb +15 -0
  36. data/lib/libcouchbase/ext/libcouchbase/create_st0.rb +23 -0
  37. data/lib/libcouchbase/ext/libcouchbase/create_st1.rb +26 -0
  38. data/lib/libcouchbase/ext/libcouchbase/create_st2.rb +32 -0
  39. data/lib/libcouchbase/ext/libcouchbase/create_st3.rb +26 -0
  40. data/lib/libcouchbase/ext/libcouchbase/crst_u.rb +20 -0
  41. data/lib/libcouchbase/ext/libcouchbase/durability_opts_st_v.rb +11 -0
  42. data/lib/libcouchbase/ext/libcouchbase/durability_opts_t.rb +14 -0
  43. data/lib/libcouchbase/ext/libcouchbase/durabilityopt_sv0.rb +63 -0
  44. data/lib/libcouchbase/ext/libcouchbase/enums.rb +1007 -0
  45. data/lib/libcouchbase/ext/libcouchbase/fragbuf.rb +18 -0
  46. data/lib/libcouchbase/ext/libcouchbase/ftshandle.rb +7 -0
  47. data/lib/libcouchbase/ext/libcouchbase/histogram.rb +34 -0
  48. data/lib/libcouchbase/ext/libcouchbase/http_request_t.rb +7 -0
  49. data/lib/libcouchbase/ext/libcouchbase/keybuf.rb +20 -0
  50. data/lib/libcouchbase/ext/libcouchbase/multicmd_ctx.rb +30 -0
  51. data/lib/libcouchbase/ext/libcouchbase/mutation_token.rb +17 -0
  52. data/lib/libcouchbase/ext/libcouchbase/n1qlhandle.rb +7 -0
  53. data/lib/libcouchbase/ext/libcouchbase/n1qlparams.rb +7 -0
  54. data/lib/libcouchbase/ext/libcouchbase/respbase.rb +29 -0
  55. data/lib/libcouchbase/ext/libcouchbase/respcounter.rb +32 -0
  56. data/lib/libcouchbase/ext/libcouchbase/respendure.rb +49 -0
  57. data/lib/libcouchbase/ext/libcouchbase/respfts.rb +40 -0
  58. data/lib/libcouchbase/ext/libcouchbase/respget.rb +44 -0
  59. data/lib/libcouchbase/ext/libcouchbase/resphttp.rb +48 -0
  60. data/lib/libcouchbase/ext/libcouchbase/respmcversion.rb +38 -0
  61. data/lib/libcouchbase/ext/libcouchbase/respn1ql.rb +41 -0
  62. data/lib/libcouchbase/ext/libcouchbase/respobseqno.rb +52 -0
  63. data/lib/libcouchbase/ext/libcouchbase/respobserve.rb +41 -0
  64. data/lib/libcouchbase/ext/libcouchbase/respserverbase.rb +32 -0
  65. data/lib/libcouchbase/ext/libcouchbase/respstats.rb +38 -0
  66. data/lib/libcouchbase/ext/libcouchbase/respstore.rb +32 -0
  67. data/lib/libcouchbase/ext/libcouchbase/respstoredur.rb +38 -0
  68. data/lib/libcouchbase/ext/libcouchbase/respsubdoc.rb +35 -0
  69. data/lib/libcouchbase/ext/libcouchbase/respviewquery.rb +67 -0
  70. data/lib/libcouchbase/ext/libcouchbase/sdentry.rb +22 -0
  71. data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +31 -0
  72. data/lib/libcouchbase/ext/libcouchbase/t.rb +7 -0
  73. data/lib/libcouchbase/ext/libcouchbase/valbuf.rb +22 -0
  74. data/lib/libcouchbase/ext/libcouchbase/valbuf_u_buf.rb +14 -0
  75. data/lib/libcouchbase/ext/libcouchbase/viewhandle.rb +7 -0
  76. data/lib/libcouchbase/ext/libcouchbase_libuv.rb +22 -0
  77. data/lib/libcouchbase/ext/tasks.rb +39 -0
  78. data/lib/libcouchbase/n1ql.rb +78 -0
  79. data/lib/libcouchbase/query_full_text.rb +147 -0
  80. data/lib/libcouchbase/query_n1ql.rb +123 -0
  81. data/lib/libcouchbase/query_view.rb +135 -0
  82. data/lib/libcouchbase/results_fiber.rb +281 -0
  83. data/lib/libcouchbase/results_native.rb +220 -0
  84. data/lib/libcouchbase/subdoc_request.rb +139 -0
  85. data/lib/libcouchbase/version.rb +5 -0
  86. data/libcouchbase.gemspec +68 -0
  87. data/spec/bucket_spec.rb +290 -0
  88. data/spec/connection_spec.rb +257 -0
  89. data/spec/design_docs_spec.rb +31 -0
  90. data/spec/error_spec.rb +26 -0
  91. data/spec/fts_spec.rb +135 -0
  92. data/spec/n1ql_spec.rb +206 -0
  93. data/spec/results_libuv_spec.rb +244 -0
  94. data/spec/results_native_spec.rb +259 -0
  95. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/design.json +1 -0
  96. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/data-0000.cbb +0 -0
  97. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/failover.json +1 -0
  98. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/meta.json +1 -0
  99. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/seqno.json +1 -0
  100. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/snapshot_markers.json +1 -0
  101. data/spec/subdoc_spec.rb +192 -0
  102. data/spec/view_spec.rb +201 -0
  103. data/windows_build.md +36 -0
  104. metadata +265 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 64cdecfc1eaee7330781885e072e3c9c6352b3ed90b646698f4fdd744a229010
4
+ data.tar.gz: 72030cf452aa9dc8e059714d94dd448095e6ead7eeb2a0f01ff660b627b14d5b
5
+ SHA512:
6
+ metadata.gz: 9b4155a992c3ad673c993e888f584d389b5fa9f278d631a77b788cda52a8dd5bcd9a9cdbbbfd7632773c3802f82f5c0c126d146cee8b4fd9b6f4dbeb900fee4e
7
+ data.tar.gz: 503ed09a72fd82edf1394c9c6337472326b1c7abe6c4cc596e5a725e468f67e8bfcc41d57075054bac8be9bca61fc784364493a8926730b37f51706890166bd6
@@ -0,0 +1,20 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ html
6
+ pkg
7
+ doc
8
+ tmp
9
+ rerun.txt
10
+ Gemfile.lock
11
+ .bundle
12
+ .idea
13
+ *.rbc
14
+ .yardoc
15
+ bin
16
+ Gemfile-custom
17
+
18
+ *.gem
19
+
20
+ *.dll
@@ -0,0 +1,3 @@
1
+ [submodule "ext/libcouchbase"]
2
+ path = ext/libcouchbase
3
+ url = https://github.com/couchbase/libcouchbase.git
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format progress
@@ -0,0 +1,38 @@
1
+ language: ruby
2
+ rvm:
3
+ - ruby-2.4.2
4
+ - ruby-2.3.5
5
+ - ruby-head
6
+ - jruby-9.1.13.0
7
+ - jruby-head
8
+ - rubinius
9
+ - rubinius-3.86
10
+ branches:
11
+ only:
12
+ - master
13
+ before_install:
14
+ - git submodule update --init --recursive
15
+ - gem install ffi
16
+ - sudo apt-get install libev-dev python-httplib2
17
+ - sudo wget https://packages.couchbase.com/releases/5.1.0/couchbase-server-enterprise_5.1.0-ubuntu14.04_amd64.deb
18
+ - sudo dpkg -i couchbase-server-enterprise_5.1.0-ubuntu14.04_amd64.deb
19
+ - sleep 8
20
+ - sudo service couchbase-server status
21
+ - /opt/couchbase/bin/couchbase-cli cluster-init -c 127.0.0.1:8091 --cluster-username=admin --cluster-password=password --cluster-ramsize=320 --cluster-index-ramsize=256 --cluster-fts-ramsize=256 --services=data,index,query,fts
22
+ - sleep 5
23
+ - /opt/couchbase/bin/couchbase-cli server-info -c 127.0.0.1:8091 -u admin -p password
24
+ - /opt/couchbase/bin/couchbase-cli bucket-create -c 127.0.0.1:8091 -u admin -p password --bucket=default --bucket-type=couchbase --bucket-ramsize=160 --bucket-replica=0 --wait
25
+ - /opt/couchbase/bin/couchbase-cli bucket-create -c 127.0.0.1:8091 -u admin -p password --bucket=test --bucket-type=couchbase --bucket-ramsize=160 --bucket-replica=0 --enable-flush=1 --wait
26
+ - sleep 1
27
+ - /opt/couchbase/bin/couchbase-cli user-manage -c 127.0.0.1:8091 -u admin -p password --set --rbac-username tester --rbac-password password123 --rbac-name "Auto Tester" --roles admin --auth-domain local
28
+ - /opt/couchbase/bin/cbrestore -x rehash=1 -b default -B default -u admin -p password ./spec/seed http://127.0.0.1:8091
29
+ before_script:
30
+ - rake compile
31
+ matrix:
32
+ allow_failures:
33
+ - rvm: jruby-head
34
+ - rvm: ruby-head
35
+ - rvm: rubinius
36
+ - rvm: rubinius-3.86
37
+ sudo: required
38
+ dist: trusty
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+
4
+ gem "rubysl", :platform => :rbx
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2016 ACAProjects
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is furnished
8
+ to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
20
+
21
+ ===
22
+
23
+ This license applies to all parts of the libcouchbase gem (Ruby FFI bindings for libcouchbase only)
24
+ Libcouchbase itself [is using the Couchbase license](https://github.com/couchbase/libcouchbase/blob/master/LICENSE)
@@ -0,0 +1,445 @@
1
+ # libcouchbase FFI bindings for Ruby
2
+
3
+ [![Build Status](https://secure.travis-ci.org/cotag/libcouchbase.svg)](http://travis-ci.org/cotag/libcouchbase)
4
+
5
+ An alternative to the official [couchbase-client](https://github.com/couchbase/couchbase-ruby-client)
6
+
7
+ * This client is non-blocking where possible using Fibers, which makes it simple to write performant code in Frameworks like [Rails](http://rubyonrails.org/).
8
+ * Client is threadsafe and reentrant
9
+
10
+ This is a low level wrapper around libcouchbase. For a more friendly ActiveModel interface see [couchbase-orm](https://github.com/acaprojects/couchbase-orm)
11
+
12
+ ## Couchbase 5 Changes
13
+
14
+ The Couchbase 5 Admin Console blows away flags on documents if you edit them in the interface.
15
+ Flags were being used to store document formats, however these were mainly implemented for compatibility with the defunct official client.
16
+
17
+
18
+ To prevent this being an issue we've made the following changes from version 1.2 of this library:
19
+
20
+ 1. All writes will result in valid JSON being saved to the database
21
+ * No more `raw strings` they will be saved as `"raw strings"`
22
+ * Existing raw strings will still be read correctly
23
+ 2. Since there are no more raw strings, append / prepend are no longer needed (not that we ever used them)
24
+
25
+
26
+ ## Runtime Support:
27
+
28
+ * Native Ruby
29
+ * Blocks the current thread while performing operations
30
+ * Multiple operations can occur simultaneously on different threads
31
+ * For [Rails](http://rubyonrails.org/) and similar, this has optimal performance when running on [Puma](http://puma.io/)
32
+ * [EventMachine](https://github.com/eventmachine/eventmachine)
33
+ * Requires the use of [em-synchrony](https://github.com/igrigorik/em-synchrony) or for the EM run block to be [wrapped by a fiber](https://github.com/igrigorik/em-http-request/blob/master/examples/fibered-http.rb#L27)
34
+ * When running [Rails](http://rubyonrails.org/) you'll have best results with [Thin](https://github.com/macournoyer/thin) and [Rack Fiber Pool](https://github.com/alebsack/rack-fiber_pool)
35
+ * Requests block the current Fiber, yielding so the reactor loop is not blocked
36
+ * [Libuv](https://github.com/cotag/libuv)
37
+ * When running [Rails](http://rubyonrails.org/) you'll have best results with [SpiderGazelle](https://github.com/cotag/spider-gazelle)
38
+ * Requests block the current Fiber, yielding so the reactor loop is not blocked
39
+
40
+ Syntax is the same across all runtimes and you can perform multiple operations simultaneously then wait for the results of those operations.
41
+
42
+ Operations are also aware of the context they are being executed in.
43
+ For instance if you perform a request in an EventMachine thread pool, it will execute as Native Ruby and on the event loop it'll be non-blocking.
44
+
45
+
46
+ ## Installation
47
+
48
+ This GEM includes the [libcouchbase c-library](https://github.com/couchbase/libcouchbase) with requires [cmake](https://cmake.org/) for the build process.
49
+ The library is built on installation.
50
+
51
+ * Ensure [cmake](https://cmake.org/install/) is installed
52
+ * Run `gem install libcouchbase`
53
+
54
+
55
+ The library is designed to run anywhere [Rails](http://rubyonrails.org/) runs:
56
+
57
+ * Ruby 2.2+
58
+ * JRuby 9.1+
59
+ * Rubinius 3.76+
60
+
61
+
62
+ Tested on the following Operating Systems:
63
+
64
+ * OSX / MacOS
65
+ * Linux
66
+ * Windows
67
+ * Ruby x64 2.4+ with MSYS2 DevKit
68
+
69
+
70
+ ## Usage
71
+
72
+ First, you need to load the library:
73
+
74
+ ```ruby
75
+ require 'libcouchbase'
76
+ ```
77
+
78
+ The client will automatically adjust configuration when the cluster rebalances its nodes when nodes are added or deleted therefore this client is "smart".
79
+ By default the client will connect to the default bucket on localhost.
80
+
81
+ ```ruby
82
+ bucket = Libcouchbase::Bucket.new
83
+ ```
84
+
85
+ To connect to other buckets, other than the default
86
+
87
+ ```ruby
88
+ # Same as Libcouchbase::Bucket.new
89
+ bucket = Libcouchbase::Bucket.new(hosts: '127.0.0.1', bucket: 'default', password: nil)
90
+
91
+ # To connect to other buckets, you can also specify multiple hosts:
92
+ bucket = Libcouchbase::Bucket.new(hosts: ['cb1.org', 'cb2.org'], bucket: 'app_data', password: 'goodluck')
93
+ ```
94
+
95
+ Connections can be configured to use `:quiet` mode. This mean it won't raise
96
+ exceptions when the given key does not exist:
97
+
98
+ ```ruby
99
+ bucket.quiet = true
100
+ bucket.get(:missing_key) #=> nil
101
+ ```
102
+
103
+ It could be useful avoiding exception handling. (See `#add` and `#replace` operations).
104
+ You can turn off these exceptions by passing `:quiet => true` when you
105
+ are instantiating the connection or change corresponding attribute:
106
+
107
+ ```ruby
108
+ bucket.quiet = false
109
+ bucket.get("missing-key") #=> raise Libcouchbase::Error::KeyNotFound
110
+ bucket.get("missing-key", :quiet => true) #=> nil
111
+ ```
112
+
113
+
114
+ The library supports both synchronous and asynchronous operations.
115
+ In asynchronous mode all operations will return control to caller
116
+ without blocking current thread. By default all operations are
117
+ synchronous, using Fibers on event loops to prevent blocking the
118
+ reactor. Use asynchronous operations if you want mulitple operations
119
+ to execute in parallel.
120
+
121
+
122
+ ```ruby
123
+ # Perform operations in Async and then wait for the results
124
+ results = []
125
+ results << bucket.get(:key1, async: true)
126
+ results << bucket.get(:key2, async: true)
127
+ bucket.wait_results(results) #=> ['key1_val', 'key2_val']
128
+
129
+ # Is equivalent to:
130
+ bucket.get(:key1, :key2) #=> ['key1_val', 'key2_val']
131
+
132
+ # Process result without waiting or blocking the thread at all
133
+ # This will execute on the couchbase reactor loop so it is
134
+ # recommended not to block in the callback - spin up a new thread
135
+ # or schedule the work to occur next_tick etc
136
+ promise = bucket.get(:key1, async: true)
137
+ promise.then { |result| puts result }
138
+ promise.catch { |error| puts error }
139
+ promise.finally { puts 'operation complete' }
140
+ ```
141
+
142
+
143
+ ### Get
144
+
145
+ ```ruby
146
+ val = bucket.get("foo")
147
+
148
+ # Get extended details
149
+ result = bucket.get("foo", extended: true)
150
+ result.key #=> "foo"
151
+ result.value #=> {some: "value"}
152
+ result.cas #=> 123445
153
+ result.metadata #=> {flags: 0}
154
+ ```
155
+
156
+
157
+ Get multiple values. In quiet mode will put `nil` values on missing
158
+ positions:
159
+
160
+ ```ruby
161
+ vals = bucket.get(:foo, :bar, "baz")
162
+ ```
163
+
164
+ Hash-like syntax
165
+
166
+ ```ruby
167
+ val = bucket[:foo]
168
+ ```
169
+
170
+ Return a key-value hash
171
+
172
+ ```ruby
173
+ val = bucket.get(:foo, :bar, "baz", assemble_hash: true)
174
+ val #=> {:foo => val1, :bar => val2, "baz" => val3}
175
+ ```
176
+
177
+
178
+ ### Touch
179
+
180
+ ```ruby
181
+ # Expire in 30 seconds
182
+ bucket.touch(:foo, expire_in: 30
183
+ bucket.touch(:foo, ttl: 30)
184
+ bucket.touch(:foo, expire_at: (Time.now + 30))
185
+ ```
186
+
187
+
188
+ ### Set
189
+
190
+ The set command will unconditionally store an object in couchbase.
191
+
192
+ ```ruby
193
+ bucket.add("foo", "bar")
194
+ bucket.add("foo", "bar", ttl: 30)
195
+ ```
196
+
197
+
198
+ ### Add
199
+
200
+ The add command will fail if the key already exists.
201
+
202
+ ```ruby
203
+ bucket.add("foo", "bar")
204
+ bucket.add("foo", "bar", ttl: 30)
205
+ ```
206
+
207
+
208
+ ### Replace
209
+
210
+ The replace command will fail if the key doesn't already exist.
211
+
212
+ ```ruby
213
+ bucket.replace("foo", "bar")
214
+ ```
215
+
216
+
217
+ ### Increment/Decrement
218
+
219
+ These commands increment the value assigned to the key.
220
+ A Couchbase increment is atomic on a distributed system.
221
+
222
+ ```ruby
223
+ bucket.set(:foo, 1)
224
+ bucket.incr(:foo) #=> 2
225
+ bucket.incr(:foo, delta: 2) #=> 4
226
+ bucket.incr(:foo, 2) #=> 6
227
+ bucket.incr(:foo, -1) #=> 5
228
+
229
+ bucket.decr(:foo) #=> 4
230
+ bucket.decr(:foo, 2) #=> 2
231
+
232
+ bucket.incr(:missing1, initial: 10) #=> 10
233
+ bucket.incr(:missing1, initial: 10) #=> 11
234
+ bucket.incr(:missing2, create: true) #=> 0
235
+ bucket.incr(:missing2, create: true) #=> 1
236
+ ```
237
+
238
+
239
+ ### Delete
240
+
241
+ ```ruby
242
+ bucket.delete(:foo)
243
+ bucket.delete(:foo, cas: 8835713818674332672)
244
+ ```
245
+
246
+
247
+ ### Flush
248
+
249
+ Delete all items in the bucket. This must be enabled on the cluster to work
250
+
251
+ ```ruby
252
+ bucket.flush
253
+ ```
254
+
255
+ ### Subdocument queries
256
+
257
+ These allow you to modify keys within documents. There is a block form.
258
+
259
+ ```ruby
260
+ c.subdoc(:foo) { |subdoc|
261
+ subdoc.get('sub.key')
262
+ subdoc.exists?('other.key')
263
+ subdoc.get_count('some.array')
264
+ } # => ["sub key val", true, 23]
265
+ ```
266
+
267
+ There is an inline form
268
+
269
+ ```ruby
270
+ c.subdoc(:foo).get(:bob).execute! # => { age: 13, working: false }
271
+ c.subdoc(:foo)
272
+ .get(:bob)
273
+ .get(:jane)
274
+ .execute! # => [{ age: 13, working: false }, { age: 47, working: true }]
275
+ ```
276
+
277
+ You can't perform lookups and mutations in the same request.
278
+
279
+ ```ruby
280
+ # multi-mutation example
281
+ c.subdoc(:foo)
282
+ .counter('bob.age', 1)
283
+ .dict_upsert('bob.address', {
284
+ number: 23
285
+ street: 'Daily Ave'
286
+ suburb: 'Some Town'
287
+ }).execute! # => 14 (the new counter value)
288
+ ```
289
+
290
+ By default, subkeys are created if they don't exist
291
+
292
+ ```ruby
293
+ c.put(:some_key, {name: 'bob'})
294
+ c.subdoc(:some_key).dict_add('non.existant.key', {
295
+ random: 123,
296
+ hash: 'values'
297
+ }).execute!
298
+ ```
299
+
300
+ Possible lookup operations are:
301
+
302
+ * `get`
303
+ * `exists?`
304
+ * `get_count`
305
+
306
+ Possible mutation operations
307
+
308
+ * `counter` increments the subkey by integer value passed
309
+ * `dict_upsert` replaces the subkey with value passed
310
+ * `dict_add`
311
+ * `array_add_first`
312
+ * `array_add_last`
313
+ * `array_add_unique`
314
+ * `array_insert`
315
+ * `replace`
316
+
317
+ You can see additional docs here: https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html
318
+
319
+
320
+ ### Views (Map/Reduce queries)
321
+
322
+ If you store structured data, they will be treated as documents and you
323
+ can handle them in map/reduce function from Couchbase Views. For example,
324
+ store a couple of posts using memcached API:
325
+
326
+ ```ruby
327
+ c['biking'] = {:title => 'Biking',
328
+ :body => 'My biggest hobby is mountainbiking. The other day...',
329
+ :date => '2009/01/30 18:04:11'}
330
+ c['bought-a-cat'] = {:title => 'Bought a Cat',
331
+ :body => 'I went to the the pet store earlier and brought home a little kitty...',
332
+ :date => '2009/01/30 20:04:11'}
333
+ c['hello-world'] = {:title => 'Hello World',
334
+ :body => 'Well hello and welcome to my new blog...',
335
+ :date => '2009/01/15 15:52:20'}
336
+ ```
337
+
338
+ Now let's create design doc with sample view and save it in file
339
+ 'blog.json':
340
+
341
+ ```JSON
342
+ {
343
+ "_id": "_design/blog",
344
+ "language": "javascript",
345
+ "views": {
346
+ "recent_posts": {
347
+ "map": "function(doc){if(doc.date && doc.title){emit(doc.date, doc.title);}}"
348
+ }
349
+ }
350
+ }
351
+ ```
352
+
353
+ This design document could be loaded into the database like this (also you can
354
+ pass the ruby Hash or String with JSON encoded document):
355
+
356
+ ```ruby
357
+ c.save_design_doc(File.open('blog.json'))
358
+ ```
359
+
360
+ To execute view you need to fetch it from design document `_design/blog`:
361
+
362
+ ```ruby
363
+ blog = c.design_docs['blog']
364
+ blog.views #=> ["recent_posts"]
365
+
366
+ # Returns an Enumerator
367
+ res = blog.view('recent_posts') #=> #<Libcouchbase::Results:0x007fbaed12c988>
368
+
369
+ # Results are lazily loaded by the enumerator
370
+ # Results are stored for re-use until `res` goes out of scope
371
+ # Actual database query happens here, by default documents are included
372
+ res.each do |row|
373
+ # Returns extended results by default
374
+ row.key
375
+ row.value
376
+ row.cas
377
+ row.metadata #=> {emitted: val, geometry: spatial_val, format: :document, flags: 0}
378
+ end
379
+
380
+ # You can however stream results to save memory and the results are not saved
381
+ res.stream do |row|
382
+ # Row is cleaned up as soon as possible
383
+ end
384
+
385
+ # For IDs only:
386
+ res = blog.view(:recent_posts, include_docs: false)
387
+ ```
388
+
389
+
390
+ ### N1QL Queries
391
+
392
+ If N1QL indexes have been created, then you can query them
393
+
394
+ ```ruby
395
+ results = bucket.n1ql
396
+ .select('*')
397
+ .from(:default)
398
+ .where('port == 10001')
399
+ .results
400
+
401
+ # Results are lazily loaded by the enumerator
402
+ # Results are stored for re-use until `results` goes out of scope
403
+ # Actual database query happens here
404
+ results.each do |row|
405
+ # Each row is a Hash of the data requested
406
+ end
407
+
408
+ # You can however stream results to save memory and the results are not saved
409
+ results.stream do |row|
410
+ # Row is cleaned up as soon as possible
411
+ end
412
+ ```
413
+
414
+
415
+ ### Full Text Search
416
+
417
+ If Full Text Search indexes have been created, then you can query them
418
+
419
+ ```ruby
420
+ results = bucket.full_text_search(:index_name, 'query')
421
+
422
+ # Results are lazily loaded by the enumerator
423
+ # Results are stored for re-use until `res` goes out of scope
424
+ # Actual database query happens here
425
+ results.each do |row|
426
+ # Each row is a Hash of the data requested
427
+ end
428
+
429
+ # You can however stream results to save memory and the results are not saved
430
+ results.stream do |row|
431
+ # Row is cleaned up as soon as possible
432
+ end
433
+ ```
434
+
435
+ Full text search supports more complex queries, you can pass in a Hash as the query
436
+ and provide any other options supported by FTS: http://developer.couchbase.com/documentation/server/current/fts/fts-queries.html
437
+
438
+ ```ruby
439
+ bucket.full_text_search(:index_name, {
440
+ boost: 1,
441
+ query: "geo.accuracy:rooftop"
442
+ }, size: 10, from: 0, explain: true, fields: ['*'])
443
+ ```
444
+
445
+