backend.elasticsearch.js | |
---|---|
this.recline = this.recline || {};
this.recline.Backend = this.recline.Backend || {};
this.recline.Backend.ElasticSearch = this.recline.Backend.ElasticSearch || {};
(function($, my) {
my.__type__ = 'elasticsearch'; | |
use either jQuery or Underscore Deferred depending on what is available | var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred; |
ElasticSearch WrapperA simple JS wrapper around an ElasticSearch endpoints. @param {String} endpoint: url for ElasticSearch type/table, e.g. for ES running on http://localhost:9200 with index twitter and type tweet it would be: http://localhost:9200/twitter/tweet @param {Object} options: set of options such as:
| my.Wrapper = function(endpoint, options) {
var self = this;
this.endpoint = endpoint;
this.options = _.extend({
dataType: 'json'
},
options); |
mappingGet ES mapping for this type/table @return promise compatible deferred object. | this.mapping = function() {
var schemaUrl = self.endpoint + '/_mapping';
var jqxhr = makeRequest({
url: schemaUrl,
dataType: this.options.dataType
});
return jqxhr;
}; |
getGet record corresponding to specified id @return promise compatible deferred object. | this.get = function(id) {
var base = this.endpoint + '/' + id;
return makeRequest({
url: base,
dataType: 'json'
});
}; |
upsertcreate / update a record to ElasticSearch backend @param {Object} doc an object to insert to the index. @return deferred supporting promise API | this.upsert = function(doc) {
var data = JSON.stringify(doc);
url = this.endpoint;
if (doc.id) {
url += '/' + doc.id;
}
return makeRequest({
url: url,
type: 'POST',
data: data,
dataType: 'json'
});
}; |
deleteDelete a record from the ElasticSearch backend. @param {Object} id id of object to delete @return deferred supporting promise API | this.remove = function(id) {
url = this.endpoint;
url += '/' + id;
return makeRequest({
url: url,
type: 'DELETE',
dataType: 'json'
});
};
this._normalizeQuery = function(queryObj) {
var self = this;
var queryInfo = (queryObj && queryObj.toJSON) ? queryObj.toJSON() : _.extend({}, queryObj);
var out = {
constant_score: {
query: {}
}
};
if (!queryInfo.q) {
out.constant_score.query = {
match_all: {}
};
} else {
out.constant_score.query = {
query_string: {
query: queryInfo.q
}
};
}
if (queryInfo.filters && queryInfo.filters.length) {
out.constant_score.filter = {
and: []
};
_.each(queryInfo.filters, function(filter) {
out.constant_score.filter.and.push(self._convertFilter(filter));
});
}
return out;
}, |
convert from Recline sort structure to ES form http://www.elasticsearch.org/guide/reference/api/search/sort.html | this._normalizeSort = function(sort) {
var out = _.map(sort, function(sortObj) {
var _tmp = {};
var _tmp2 = _.clone(sortObj);
delete _tmp2['field'];
_tmp[sortObj.field] = _tmp2;
return _tmp;
});
return out;
},
this._convertFilter = function(filter) {
var out = {};
out[filter.type] = {}
if (filter.type === 'term') {
out.term[filter.field] = filter.term.toLowerCase();
} else if (filter.type === 'geo_distance') {
out.geo_distance[filter.field] = filter.point;
out.geo_distance.distance = filter.distance;
out.geo_distance.unit = filter.unit;
}
return out;
}, |
query@return deferred supporting promise API | this.query = function(queryObj) {
var esQuery = (queryObj && queryObj.toJSON) ? queryObj.toJSON() : _.extend({}, queryObj);
esQuery.query = this._normalizeQuery(queryObj);
delete esQuery.q;
delete esQuery.filters;
if (esQuery.sort && esQuery.sort.length > 0) {
esQuery.sort = this._normalizeSort(esQuery.sort);
}
var data = {source: JSON.stringify(esQuery)};
var url = this.endpoint + '/_search';
var jqxhr = makeRequest({
url: url,
data: data,
dataType: this.options.dataType
});
return jqxhr;
}
}; |
Recline ConnectorsRequires URL of ElasticSearch endpoint to be specified on the dataset via the url attribute. | |
ES options which are passed through to | my.esOptions = {}; |
fetch | my.fetch = function(dataset) {
var es = new my.Wrapper(dataset.url, my.esOptions);
var dfd = new Deferred();
es.mapping().done(function(schema) {
if (!schema){
dfd.reject({'message':'Elastic Search did not return a mapping'});
return;
} |
only one top level key in ES = the type so we can ignore it | var key = _.keys(schema)[0];
var fieldData = _.map(schema[key].properties, function(dict, fieldName) {
dict.id = fieldName;
return dict;
});
dfd.resolve({
fields: fieldData
});
})
.fail(function(arguments) {
dfd.reject(arguments);
});
return dfd.promise();
}; |
save | my.save = function(changes, dataset) {
var es = new my.Wrapper(dataset.url, my.esOptions);
if (changes.creates.length + changes.updates.length + changes.deletes.length > 1) {
var dfd = new Deferred();
msg = 'Saving more than one item at a time not yet supported';
alert(msg);
dfd.reject(msg);
return dfd.promise();
}
if (changes.creates.length > 0) {
return es.upsert(changes.creates[0]);
}
else if (changes.updates.length >0) {
return es.upsert(changes.updates[0]);
} else if (changes.deletes.length > 0) {
return es.remove(changes.deletes[0].id);
}
}; |
query | my.query = function(queryObj, dataset) {
var dfd = new Deferred();
var es = new my.Wrapper(dataset.url, my.esOptions);
var jqxhr = es.query(queryObj);
jqxhr.done(function(results) {
var out = {
total: results.hits.total
};
out.hits = _.map(results.hits.hits, function(hit) {
if (!('id' in hit._source) && hit._id) {
hit._source.id = hit._id;
}
return hit._source;
});
if (results.facets) {
out.facets = results.facets;
}
dfd.resolve(out);
}).fail(function(errorObj) {
var out = {
title: 'Failed: ' + errorObj.status + ' code',
message: errorObj.responseText
};
dfd.reject(out);
});
return dfd.promise();
}; |
makeRequestJust $.ajax but in any headers in the 'headers' attribute of this Backend instance. Example: var jqxhr = this._makeRequest({ url: the-url }); | var makeRequest = function(data, 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);
};
}(jQuery, this.recline.Backend.ElasticSearch));
|