diff --git a/src/backend/base.js b/src/backend/base.js index 1b06dc01..94cccf4f 100644 --- a/src/backend/base.js +++ b/src/backend/base.js @@ -99,6 +99,32 @@ this.recline.Backend = this.recline.Backend || {}; query: function(model, queryObj) { }, + // ### _makeRequest + // + // Just $.ajax but in any headers in the 'headers' attribute of this + // Backend instance. Example: + // + //
+    // var jqxhr = this._makeRequest({
+    //   url: the-url
+    // });
+    // 
+ _makeRequest: function(data) { + var headers = this.get('headers'); + var extras = {}; + if (headers) { + extras = { + beforeSend: function(req) { + _.each(headers, function(value, key) { + req.setRequestHeader(key, value); + }); + } + }; + } + var data = _.extend(extras, data); + return $.ajax(data); + }, + // convenience method to convert simple set of documents / rows to a QueryResult _docsToQueryResult: function(rows) { var hits = _.map(rows, function(row) { diff --git a/src/backend/elasticsearch.js b/src/backend/elasticsearch.js index 03448277..546c0c8a 100644 --- a/src/backend/elasticsearch.js +++ b/src/backend/elasticsearch.js @@ -6,37 +6,39 @@ this.recline.Backend = this.recline.Backend || {}; // // Connecting to [ElasticSearch](http://www.elasticsearch.org/). // - // To use this backend ensure your Dataset has one of the following - // attributes (first one found is used): + // Usage: + // + //
+  // var backend = new recline.Backend.ElasticSearch({
+  //   // optional as can also be provided by Dataset/Document
+  //   url: {url to ElasticSearch endpoint i.e. ES 'type/table' url - more info below}
+  //   // optional
+  //   headers: {dict of headers to add to each request}
+  // });
+  //
+  // @param {String} url: url for ElasticSearch type/table, e.g. for ES running
+  // on localhost:9200 with index // twitter and type tweet it would be:
+  // 
+  // 
http://localhost:9200/twitter/tweet
+ // + // This url is optional since the ES endpoint url may be specified on the the + // dataset (and on a Document by the document having a dataset attribute) by + // having one of the following (see also `_getESUrl` function): // //
   // elasticsearch_url
   // webstore_url
   // url
   // 
- // - // This should point to the ES type url. E.G. for ES running on - // localhost:9200 with index twitter and type tweet it would be - // - //
http://localhost:9200/twitter/tweet
my.ElasticSearch = my.Base.extend({ __type__: 'elasticsearch', readonly: false, - _getESUrl: function(dataset) { - var out = dataset.get('elasticsearch_url'); - if (out) return out; - out = dataset.get('webstore_url'); - if (out) return out; - out = dataset.get('url'); - return out; - }, sync: function(method, model, options) { var self = this; if (method === "read") { if (model.__type__ == 'Dataset') { - var base = self._getESUrl(model); - var schemaUrl = base + '/_mapping'; - var jqxhr = $.ajax({ + var schemaUrl = self._getESUrl(model) + '/_mapping'; + var jqxhr = this._makeRequest({ url: schemaUrl, dataType: 'jsonp' }); @@ -57,36 +59,75 @@ this.recline.Backend = this.recline.Backend || {}; return dfd.promise(); } else if (model.__type__ == 'Document') { var base = this._getESUrl(model.dataset) + '/' + model.id; - return $.ajax({ + return this._makeRequest({ url: base, dataType: 'json' }); } } else if (method === 'update') { if (model.__type__ == 'Document') { - var data = JSON.stringify(model.toJSON()); - var base = this._getESUrl(model.dataset); - if (model.id) { - base += '/' + model.id; - } - return $.ajax({ - url: base, - type: 'POST', - data: data, - dataType: 'json' - }); + return this.upsert(model.toJSON(), this._getESUrl(model.dataset)); } } else if (method === 'delete') { if (model.__type__ == 'Document') { - var base = this._getESUrl(model.dataset) + '/' + model.id; - return $.ajax({ - url: base, - type: 'DELETE', - dataType: 'json' - }); + var url = this._getESUrl(model.dataset); + return this.delete(model.id, url); } } }, + + // ### upsert + // + // create / update a document to ElasticSearch backend + // + // @param {Object} doc an object to insert to the index. + // @param {string} url (optional) url for ElasticSearch endpoint (if not + // defined called this._getESUrl() + upsert: function(doc, url) { + var data = JSON.stringify(doc); + url = url ? url : this._getESUrl(); + if (doc.id) { + url += '/' + doc.id; + } + return this._makeRequest({ + url: url, + type: 'POST', + data: data, + dataType: 'json' + }); + }, + + // ### delete + // + // Delete a document from the ElasticSearch backend. + // + // @param {Object} id id of object to delete + // @param {string} url (optional) url for ElasticSearch endpoint (if not + // provided called this._getESUrl() + delete: function(id, url) { + url = url ? url : this._getESUrl(); + url += '/' + id; + return this._makeRequest({ + url: url, + type: 'DELETE', + dataType: 'json' + }); + }, + + // ### _getESUrl + // + // get url to ElasticSearch endpoint (see above) + _getESUrl: function(dataset) { + if (dataset) { + var out = dataset.get('elasticsearch_url'); + if (out) return out; + out = dataset.get('webstore_url'); + if (out) return out; + out = dataset.get('url'); + return out; + } + return this.get('url'); + }, _normalizeQuery: function(queryObj) { var out = queryObj.toJSON ? queryObj.toJSON() : _.extend({}, queryObj); if (out.q !== undefined && out.q.trim() === '') { @@ -123,7 +164,7 @@ this.recline.Backend = this.recline.Backend || {}; var queryNormalized = this._normalizeQuery(queryObj); var data = {source: JSON.stringify(queryNormalized)}; var base = this._getESUrl(model); - var jqxhr = $.ajax({ + var jqxhr = this._makeRequest({ url: base + '/_search', data: data, dataType: 'jsonp'