Name Date Size

..11-Feb-20204 KiB

.gitignoreH A D11-Feb-202065

etc/couchdb/default.d/H11-Feb-20204 KiB

MakefileH A D11-Feb-2020765

README.mdH A D11-Feb-202010 KiB

rebarH A D11-Feb-2020116.2 KiB

rebar.configH A D11-Feb-2020101

rebar.config.scriptH A D11-Feb-2020686

share/www/script/test/H11-Feb-20204 KiB

src/H11-Feb-20204 KiB

test/H11-Feb-20204 KiB

README.md

1Welcome to the world of GeoCouch
2================================
3
4GeoCouch is a spatial extension for Apache CouchDB and Couchbase.
5
6Prerequisites
7-------------
8
9A working installation of CouchDB with corresponding source
10code. GeoCouch works best with Couchbase and the latest stable releases of
11CouchDB (should be >= 1.1.0).
12
13### Understanding the branches:
14
15This repository contains several branches, please make sure you use
16the correct one:
17
18 - master: works with the CouchDB master branch from Couchbase's repo
19   (https://github.com/couchbase/couchdb)
20 - couchdb1.1.x: works with Apache CouchDB 1.1.x
21 - couchdb1.2.x: works with Apache CouchDB 1.2.x
22 - couchdb1.3.x: works with Apache CouchDB 1.3.x
23
24Installation
25------------
26
27### Get GeoCouch:
28
29    git clone https://github.com/couchbase/geocouch.git
30    cd geocouch
31
32### Compilation
33
34Note: Always replace `<vanilla-couch>` with the path to your CouchDB
35source and `<geocouch>` with the location of the GeoCouch source.
36
37Set the `COUCH_SRC` environment to the directory that contains the
38CouchDB core source (`<vanilla-couch>/src/couchdb/`).
39
40    export COUCH_SRC=<vanilla-couch>/src/couchdb
41
42Run "make" in your <geocouch> directory
43
44    make
45
46Copy the configuration file for GeoCouch from
47`<geocouch>/etc/couchdb/default.d/` to
48`<vanilla-couch>/etc/couchdb/default.d/`
49
50    cp <geocouch>/etc/couchdb/default.d/geocouch.ini <vanilla-couch>/etc/couchdb/default.d/
51
52### Futon tests
53
54To make sure your installation is working also copy the Futon tests
55over (from `<geocouch>/share/www/script/test` to
56`<vanilla-couch>/share/www/script/test`):
57
58    cp <geocouch>/share/www/script/test/* <vanilla-couch>/share/www/script/test/
59
60Add the test to `<vanilla-couch>/share/www/script/couch_tests.js`
61
62    loadTest("spatial.js");
63    loadTest("list_spatial.js");
64    loadTest("etags_spatial.js");
65    loadTest("multiple_spatial_rows.js");
66    loadTest("spatial_compaction.js");
67    loadTest("spatial_design_docs.js");
68    loadTest("spatial_bugfixes.js");
69    loadTest("spatial_merging.js");
70    loadTest("spatial_offsets.js");
71
72### Run CouchDB with GeoCouch
73
74The compiled beam files from GeoCouch need to be in Erlang's path,
75which can be set with the `ERL_FLAGS` environment variable:
76
77    export ERL_FLAGS="-pa <geocouch>/ebin"
78
79If you run a dev instance with CouchDB's `./utils/run` you can also
80define it on startup:
81
82    ERL_FLAGS="-pa <geocouch>/ebin" <vanilla-couch>/utils/run
83
84
85Using GeoCouch
86--------------
87
88Create a database:
89
90    curl -X PUT http://127.0.0.1:5984/places
91
92Add a Design Document with a spatial function:
93
94    curl -X PUT -d '{"spatial":{"points":"function(doc) {\n    if (doc.loc) {\n        emit({\n            type: \"Point\",\n            coordinates: [doc.loc[0], doc.loc[1]]\n        }, [doc._id, doc.loc]);\n    }};"}}' http://127.0.0.1:5984/places/_design/main
95
96Put some data into it:
97
98    curl -X PUT -d '{"loc": [-122.270833, 37.804444]}' http://127.0.0.1:5984/places/oakland
99    curl -X PUT -d '{"loc": [10.898333, 48.371667]}' http://127.0.0.1:5984/places/augsburg
100
101Make a bounding box request:
102
103    curl -X GET 'http://localhost:5984/places/_design/main/_spatial/points?bbox=0,0,180,90'
104
105It should return:
106
107    {"update_seq":3,"rows":[
108    {"id":"augsburg","bbox":[10.898333,48.371667,10.898333,48.371667],"geometry":{"type":"Point","coordinates":[10.898333,48.371667]},"value":["augsburg",[10.898333,48.371667]]}
109    ]}
110
111The Design Document Function
112----------------------------
113
114function(doc) {
115    if (doc.loc) {
116        emit({
117            type: "Point",
118            coordinates: [doc.loc[0], doc.loc[1]]
119        }, [doc._id, doc.loc]);
120    }};"
121
122It uses the emit() from normal views. The key is a
123[GeoJSON](http://geojson.org) geometry, the value is any arbitrary JSON. All
124geometry types (even GemetryCollections) are supported.
125
126If the GeoJSON geometry contains a `bbox` property it will be used instead
127of calculating it from the geometry (even if it's wrong, i.e. is not
128the actual bounding box).
129
130
131Bounding box search and the date line
132-------------------------------------
133
134A common problem when performing bounding box searches is the date
135line/poles. As the bounding box follows the GeoJSON specification,
136where the first two numbers are the lower left coordinate, the last
137two numbers the upper right coordinate, it is easy to map it over the
138date line/poles. The lower coordinate would have a higher value than
139the upper one. Such a bounding box has a seems invalid at first
140glance, but isn't. For example a bounding box like `110,-60,-30,15`
141would include Australia and South America, but not Africa.
142
143GeoCouch operates on a plane and doesn't perform spherical
144calculations. Therefore the bounds of the plane needs to be set
145explicitly with the `plane_bounds` parameter. If bounding boxes are
146flipped, a search across those bounds will be performed
147automatically. Give it a try (with the same Design Document as
148above). Insert some Documents:
149
150    curl -X PUT -d '{"loc": [17.15, -22.566667]}' http://127.0.0.1:5984/places/namibia
151    curl -X PUT -d '{"loc": [135, -25]}' http://127.0.0.1:5984/places/australia
152    curl -X PUT -d '{"loc": [-52.95, -10.65]}' http://127.0.0.1:5984/places/brasilia
153
154And request only Australia and Brasilia:
155
156    curl -X GET 'http://localhost:5984/places/_design/main/_spatial/points?bbox=110,-60,-30,15&plane_bounds=-180,-90,180,90'
157
158The result is as expected:
159
160    {"update_seq":6,"rows":[
161    {"id":"australia","bbox":[135,-25,135,-25],"geometry":{"type":"Point","coordinates":[135,-25]},"value":["australia",[135,-25]]},
162    {"id":"brasilia","bbox":[-52.95,-10.65,-52.95,-10.65],"geometry":{"type":"Point","coordinates":[-52.95,-10.65]},"value":["brasilia",[-52.95,-10.65]]}
163    ]}
164
165The bounding with the same numbers, but different order
166(`-30,-60,110,15`) would only return Namibia:
167
168    curl -X GET 'http://localhost:5984/places/_design/main/_spatial/points?bbox=-30,-60,110,15&plane_bounds=-180,-90,180,90'
169
170    {"update_seq":6,"rows":[
171    {"id":"namibia","bbox":[17.15,-22.566667,17.15,-22.566667],"geometry":{"type":"Point","coordinates":[17.15,-22.566667]},"value":["namibia",[17.15,-22.566667]]}
172    ]}
173
174List function support
175---------------------
176
177GeoCouch supports List functions just as CouchDB does for Views. This way
178you can output any arbitrary format, e.g. GeoRSS.
179
180As an example we output the points as WKT. Add a new Design Document
181with an additional List function (the rest is the same as above). Make
182sure you use the right `_rev`:
183
184    curl -X PUT -d '{"_rev": "1-121efc747b00743b8c7621ffccf1ac40", "lists": {"wkt": "function(head, req) {\n    var row;\n    while (row = getRow()) {\n        send(\"POINT(\" + row.geometry.coordinates.join(\" \") + \")\\n\");\n    }\n};"}, "spatial":{"points":"function(doc) {\n    if (doc.loc) {\n        emit({\n            type: \"Point\",\n            coordinates: [doc.loc[0], doc.loc[1]]\n        }, [doc._id, doc.loc]);\n    }};"}}' http://127.0.0.1:5984/places/_design/main
185
186Now you can request this List function as you would do for CouchDB,
187though with a different Design handler (`_spatial/_list` instead of
188`_list` ):
189
190    curl -X GET 'http://localhost:5984/places/_design/main/_spatial/_list/wkt/points?bbox=-180,-90,180,90'
191
192The result is:
193
194    POINT(10.898333 48.371667)
195    POINT(-122.270833 37.804444)
196    POINT(17.15 -22.566667)
197    POINT(135 -25)
198    POINT(-52.95 -10.65)
199
200Using List functions from Design Documents other than the one containing the
201Spatial functions is supported as well. This time we add the Document
202ID in parenthesis:
203
204    curl -X PUT -d '{"lists": {"wkt": "function(head, req) {\n    var row;\n    while (row = getRow()) {\n        send(\"POINT(\" + row.geometry.coordinates.join(\" \") + \") (\" + row.id + \")\\n\");\n    }\n};"}}' http://127.0.0.1:5984/places/_design/listfunonly
205
206    curl -X GET 'http://localhost:5984/places/_design/listfunonly/_spatial/_list/wkt/main/points?bbox=-180,-90,180,90'
207
208
209Other supported query arguments
210-------------------------------
211
212### stale ###
213`stale=ok` is supported. The spatial index won't be rebuilt even if
214new Documents were added. It works for normal spatial queries as well
215as for the spatial List functions.
216
217### count ###
218`count` is a boolean. `count=true` will only return the number of geometries
219the query will return, not the geometry themselves.
220
221    curl -X GET 'http://localhost:5984/places/_design/main/_spatial/points?bbox=0,0,180,90&count=true'
222
223    {"count":1}
224
225### limit ###
226With `limit` you can limit the number of rows that should be returned.
227
228    curl -X GET 'http://localhost:5984/places/_design/main/_spatial/points?bbox=-180,-90,180,90&limit=2'
229
230    {"update_seq":8,"rows":[
231    {"id":"augsburg","bbox":[10.898333,48.371667,10.898333,48.371667],"geometry":{"type":"Point","coordinates":[10.898333,48.371667]},"value":["augsburg",[10.898333,48.371667]]},
232    {"id":"oakland","bbox":[-122.270833,37.804444,-122.270833,37.804444],"geometry":{"type":"Point","coordinates":[-122.270833,37.804444]},"value":["oakland",[-122.270833,37.804444]]}
233    ]}
234
235### skip ###
236With `skip` you start to return the results at a certain offset.
237
238    curl -X GET 'http://localhost:5984/places/_design/main/_spatial/points?bbox=-180,-90,180,90&skip=3'
239
240    {"update_seq":8,"rows":[
241    {"id":"australia","bbox":[135,-25,135,-25],"geometry":{"type":"Point","coordinates":[135,-25]},"value":["australia",[135,-25]]},
242    {"id":"brasilia","bbox":[-52.95,-10.65,-52.95,-10.65],"geometry":{"type":"Point","coordinates":[-52.95,-10.65]},"value":["brasilia",[-52.95,-10.65]]}
243    ]}
244
245
246Compaction, cleanup and info
247----------------------------
248
249The API of GeoCouch's spatial indexes is similar to the one for the
250Views. Compaction of spatial indexes is per Design Document, thus:
251
252    curl -X POST 'http://localhost:5984/places/_design/main/_spatial/_compact' -H 'Content-Type: application/json'
253
254To cleanup spatial indexes that are no longer in use (this is per database):
255
256    curl -X POST 'http://localhost:5984/places/_spatial_cleanup' -H 'Content-Type: application/json'
257
258To get information about the spatial indexes of a certain Design
259Document use the the `_info` handler:
260
261    curl -X GET 'http://localhost:5984/places/_design/main/_spatial/_info'
262