Name Date Size

..11-Feb-20204 KiB

.gitignoreH A D11-Feb-202047

EmakefileH A D11-Feb-2020224

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

MakefileH A D11-Feb-2020915

README.mdH A D11-Feb-20208.1 KiB

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

src/H11-Feb-20204 KiB

README.md

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