Skip to content

Instantly share code, notes, and snippets.

@italoag
Last active November 17, 2017 20:09
Show Gist options
  • Save italoag/e196a7b263bd42730733338c07380946 to your computer and use it in GitHub Desktop.
Save italoag/e196a7b263bd42730733338c07380946 to your computer and use it in GitHub Desktop.
CouchDB 2.1 + Dreyfus + Clouseau

Introduce Dreyfus into CouchDB

1. download couchdb

git clone https://github.com/apache/couchdb.git

2. switch to branch

cd couchdb

3. modify rebar.config.script

DreyfusDep = [
  {dreyfus, ".*", {git, "https://github.com/cloudant-labs/dreyfus", {branch, "master"}}}
],

HastingDep = [
  {hastings, ".*", {git, "https://github.com/cloudant-labs/hastings", {branch, "master"}}}
],

EastonDep = [
  {easton, ".*", {git, "https://github.com/cloudant-labs/easton", {branch, "master"}}}
],
AddConfig = [
    ...
    -    {deps, lists:map(MakeDep, DepDescs)},
    +    {deps, lists:map(MakeDep, DepDescs) ++ DreyfusDep ++ HastingDep ++ EastonDep},
    ...
end,

configure CouchDB and its dependencies

./configure --disable-fauxton --disable-docs

add dreyfus and hastings to application list to be started

a. add dreyfus_epi and hastings_epi plugin to couch_epi.config under rel/apps/ directory

{plugins, [
    couch_db_epi,
    chttpd_epi,
    couch_index_epi,
    dreyfus_epi,
    hastings_epi,
    global_changes_epi,
    mango_epi,
    mem3_epi,
    setup_epi
]}.

b. add dreyfus and hastings to reltool.config under rel directory

{sys, [

    {rel, "couchdb", "2.1.0", [
        ...
        couch_peruser,
        ddoc_cache,
        dreyfus,
        hastings,
        ets_lru,
        ...
    ]},
    %% couchdb

    {app, couch_peruser, [{incl_cond, include}]},
    {app, ddoc_cache, [{incl_cond, include}]},
    {app, dreyfus, [{incl_cond, include}]},
    {app, hastings, [{incl_cond, include}]},
    {app, ets_lru, [{incl_cond, include}]},
 ]}

c. download dreyfus.js to share/server/dreyfus.js

curl https://raw.githubusercontent.com/cloudant/couchdb/c323f194328822385aa1bb2ab15b927cc604c4b7/share/server/dreyfus.js > share/server/dreyfus.js

d. modify file support/build_js.escript

main([]) ->
    JsFiles = [...
               "share/server/dreyfus.js",
               "share/server/loop.js"],

    CoffeeFiles = [...
                   "share/server/dreyfus.js",
                   "share/server/coffee-script.js",
                   "share/server/loop.js"],

e. add the exposed functions to share/server/loop.js to be able to call them in a view

function create_sandbox() {
  try {
      ...
      sandbox.index = Dreyfus.index;
  } catch (e) {
    //log(e.toSource());
  }
};

var Loop = function() {
  var line, cmd, cmdkey, dispatch = {
    ...
    "index_doc": Dreyfus.indexDoc
  };

f. talking To Clouseau add lines in rel/overlay/etc/local.ini and rel/overlay/etc/default.ini

[dreyfus]
name = {{clouseau_name}}

g. modify file dev/run

  "cluster_port": cluster_port,
  "backend_port": backend_port,
  "fauxton_root": fauxton_root,
  "clouseau_name": "clouseau%d@127.0.0.1" % (idx+1),
  "uuid": "fake_uuid_for_dev"

Enable spatial.js for hastings

a. Create spatial.js under share/server directory using below content

var Spatial = (function() {

  var index_results = []; // holds temporary emitted values during index

  function handleIndexError(err, doc) {
    if (err == "fatal_error") {
      throw(["error", "map_runtime_error", "function raised 'fatal_error'"]);
    } else if (err[0] == "fatal") {
      throw(err);
    }
    var message = "function raised exception " + err.toSource();
    if (doc) message += " with doc._id " + doc._id;
    log(message);
  };

  return {
    index: function(value, options) {
        index_results.push([value, options || {}]);
    },

    indexDoc: function(doc) {
      Couch.recursivelySeal(doc);
      var buf = [];
      for each (fun in State.funs) {
        index_results = [];
        try {
          fun(doc);
          buf.push(index_results);
        } catch (err) {
          handleIndexError(err, doc);
          buf.push([]);
        }
      }
      print(JSON.stringify(buf));
    }

  }
})();

b. add sandbox.st_index = Spatial.index; to loop.js under share/server directory

function create_sandbox() {
  try {
      ...
      sandbox.st_index = Spatial.index;
  } catch (e) {
    //log(e.toSource());
  }
};

var Loop = function() {
  var line, cmd, cmdkey, dispatch = {
    ...
   "st_index_doc": Spatial.indexDoc
  };

c. add "st_index_doc": Spatial.indexDoc branch to loop.js under share/server directory

var Loop = function() {
  var line, cmd, cmdkey, dispatch = {
    "ddoc"     : DDoc.ddoc,
    // "view"    : Views.handler,
    ...
    "st_index_doc": Spatial.indexDoc
  };

d. add share/server/spatial.js to build_js.escript under support directory

main([]) ->
    JsFiles = ["share/server/json2.js",
               ...
               "share/server/spatial.js",
               "share/server/loop.js"],

    CoffeeFiles = ["share/server/json2.js",
                   ...
                   "share/server/spatial.js",
                   "share/server/coffee-script.js",
                   "share/server/loop.js"],

Change on hastings to be compatible with CouchDB

a. in src/hastings_index_updater.erl delete the line that says {user, cloudant_util:customer_name(Db)},.

Enable Geospatial search

Add the following entries to default.ini under couchdb/rel/overlay/etc

[hastings]
enabled = true

Enjoy GeoSpatial Index in CouchDB

After making couchdb with enabled hastings, you can add documents with geo information to database and perform search.

jiangphs-mbp:geotest jiangph$ curl -u foo:bar -X GET 'http://localhost:15984/reltest1/_design/geodd/_geo/geoidx?bbox=-180,-90,180,90&limit=2' | python -m json.tool
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   301  100   301    0     0     97      0  0:00:03  0:00:03 --:--:--    97
{
    "bookmark": "g2wAAAABaANkAA9ub2RlMkAxMjcuMC4wLjFsAAAAAmIgAAAAYj____9qaAJtAAAAIDc5ZjE0YjY0YzU3NDYxNTg0YjE1MjEyM2UzOGE2NDQ5RkBUsmENOjDEag",
    "rows": [
        {
            "geometry": {
                "coordinates": [
                    -71.13687953,
                    42.34690635
                ],
                "type": "Point"
            },
            "id": "79f14b64c57461584b152123e38a6449",
            "rev": "1-13051c832df60ec3e9869cdc801a2104"
        }
    ]
}

Troubleshooting Hasting

Case 1: noproc error when triggering Geo indexing

{"error":"{noproc,\n    {gen_server,call,\n        [hastings_index_manager,\n         {get_index,<<\"shards/e0000000-ffffffff/reltest.1477017301\">>,\n             {h_idx,undefined,undefined,<<\"_design/geodd\">>,<<\"geoidx\">>,\n                 <<\"function(doc) {if (doc.geometry && doc.geometry.coordinates) {st_index(doc.geometry);}}\">>,\n                 <<\"javascript\">>,<<\"rtree\">>,2,4326,0,\n                 <<\"e66df316792ab411705e2741bba44371\">>}},\n         infinity]}}","reason":"[{gen_server,call,3,[{file,\"gen_server.erl\"},{line,212}]},\n {hastings_rpc,get_index_pid,3,[{file,\"src/hastings_rpc.erl\"},{line,64}]},\n {hastings_rpc,search,4,[{file,\"src/hastings_rpc.erl\"},{line,22}]},\n {rexi_server,init_p,3,[{file,\"src/rexi_server.erl\"},{line,139}]}]"}

Solution: Need to check log file and see whether hastings application has been started and see whether there is entry about startup of hastings server. If not, review section add hastings to application list to be started

[info] 2016-10-21T10:01:51.919228Z node1@127.0.0.1 <0.7.0> -------- Application couch_replicator started on node 'node1@127.0.0.1'
[info] 2016-10-21T10:01:51.919320Z node1@127.0.0.1 <0.7.0> -------- Application bear started on node 'node1@127.0.0.1'
[info] 2016-10-21T10:01:51.919397Z node1@127.0.0.1 <0.7.0> -------- Application easton started on node 'node1@127.0.0.1'
[info] 2016-10-21T10:01:51.921395Z node1@127.0.0.1 <0.7.0> -------- Application hastings started on node 'node1@127.0.0.1'
[info] 2016-10-21T10:01:51.922600Z node1@127.0.0.1 <0.7.0> -------- Application global_changes started on node 'node1@127.0.0.1'
[info] 2016-10-21T10:01:51.922632Z node1@127.0.0.1 <0.7.0> -------- Application couch_plugins started on node 'node1@127.0.0.1'
[info] 2016-10-21T10:01:51.955120Z node1@127.0.0.1 <0.7.0> -------- Application runtime_tools started on node 'node1@127.0.0.1'
[info] 2016-10-21T10:01:51.955571Z node1@127.0.0.1 <0.7.0> -------- Application ddoc_cache started on node 'node1@127.0.0.1'
[info] 2016-10-21T10:01:51.955855Z node1@127.0.0.1 <0.7.0> -------- Application couch_index started on node 'node1@127.0.0.1'

Case 2: unknown_command error when triggering Geo indexing

{
    "error": "{nocatch,{unknown_command,<<\"unknown command 'st_index_doc'\">>}}",
    "reason": "[{couch_os_process,prompt,2,[{file,\"src/couch_os_process.erl\"},{line,59}]},\n {couch_query_servers,proc_prompt,2,\n                      [{file,\"src/couch_query_servers.erl\"},{line,427}]},\n {hastings_index_updater,load_docs,2,\n                         [{file,\"src/hastings_index_updater.erl\"},{line,100}]},\n {couch_db,conv_to_full_doc_info,2,[{file,\"src/couch_db.erl\"},{line,1533}]},\n {couch_bt_engine,drop_reductions,4,\n                  [{file,\"src/couch_bt_engine.erl\"},{line,828}]},\n {couch_btree,stream_kv_node2,8,[{file,\"src/couch_btree.erl\"},{line,783}]},\n {couch_btree,fold,4,[{file,\"src/couch_btree.erl\"},{line,220}]},\n {couch_bt_engine,fold_changes,5,\n                  [{file,\"src/couch_bt_engine.erl\"},{line,431}]}]"
}

Solution: Need to reivew section enable spatial.js for hastings and decide whether all steps are taken.

Build couchdb

make

Start Couchdb

dev/run --admin=admin:mysecretpassword

Download and Start Clouseau

git clone https://github.com/cloudant-labs/clouseau
cd clouseau
mvn scala:run -Dlauncher=clouseau1

Search

Feel free to follow our tuturials for search: https://cloudant.com/for-developers/search/ and https://cloudant.com/blog/search-faceting-from-scratch–2. There is also video tutorial available at https://www.youtube.com/watch?v=IdiCmKINL9g.

Reference

Introduce GeoSpatial Index To CouchDB https://github.com/cloudant/hastings/wiki/Introduce-GeoSpatial-Index-To-CouchDB

Adding dreyfus to couchdb https://gist.github.com/rnewson/bdb8e84dcd56beb533b1

Enable Full Text Search in Apache CouchDB https://cloudant.com/blog/enable-full-text-search-in-apache-couchdb/#.WB9FOZNS1-U

Search https://cloudant.com/for-developers/search/

Build and query a search index https://cloudant.com/blog/search-faceting-from-scratch–2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment