[#54,backend/es][m]: ElasticSearch backend (readonly atm) - fixes #54.
This commit is contained in:
75
src/backend/elasticsearch.js
Normal file
75
src/backend/elasticsearch.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
this.recline = this.recline || {};
|
||||||
|
this.recline.Backend = this.recline.Backend || {};
|
||||||
|
|
||||||
|
(function($, my) {
|
||||||
|
// ## ElasticSearch Backend
|
||||||
|
//
|
||||||
|
// Connecting to [ElasticSearch](http://www.elasticsearch.org/)
|
||||||
|
//
|
||||||
|
// To use this backend ensure your Dataset has a elasticsearch_url,
|
||||||
|
// webstore_url or url attribute (used in that order)
|
||||||
|
my.ElasticSearch = Backbone.Model.extend({
|
||||||
|
_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({
|
||||||
|
url: schemaUrl,
|
||||||
|
dataType: 'jsonp'
|
||||||
|
});
|
||||||
|
var dfd = $.Deferred();
|
||||||
|
my.wrapInTimeout(jqxhr).done(function(schema) {
|
||||||
|
// 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;
|
||||||
|
});
|
||||||
|
model.fields.reset(fieldData);
|
||||||
|
dfd.resolve(model, jqxhr);
|
||||||
|
})
|
||||||
|
.fail(function(arguments) {
|
||||||
|
dfd.reject(arguments);
|
||||||
|
});
|
||||||
|
return dfd.promise();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert('This backend currently only supports read operations');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
query: function(model, queryObj) {
|
||||||
|
var base = this._getESUrl(model);
|
||||||
|
var data = _.extend({}, queryObj);
|
||||||
|
var jqxhr = $.ajax({
|
||||||
|
url: base + '/_search',
|
||||||
|
data: data,
|
||||||
|
dataType: 'jsonp'
|
||||||
|
});
|
||||||
|
var dfd = $.Deferred();
|
||||||
|
// TODO: fail case
|
||||||
|
jqxhr.done(function(results) {
|
||||||
|
model.docCount = results.hits.total;
|
||||||
|
var docs = _.map(results.hits.hits, function(result) {
|
||||||
|
var _out = result._source;
|
||||||
|
_out.id = result._id;
|
||||||
|
return _out;
|
||||||
|
});
|
||||||
|
dfd.resolve(docs);
|
||||||
|
});
|
||||||
|
return dfd.promise();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
recline.Model.backends['elasticsearch'] = new my.ElasticSearch();
|
||||||
|
|
||||||
|
}(jQuery, this.recline.Backend));
|
||||||
|
|
||||||
124
test/backend.elasticsearch.test.js
Normal file
124
test/backend.elasticsearch.test.js
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
(function ($) {
|
||||||
|
module("Backend ElasticSearch");
|
||||||
|
|
||||||
|
var mapping_data = {
|
||||||
|
"note": {
|
||||||
|
"properties": {
|
||||||
|
"_created": {
|
||||||
|
"format": "dateOptionalTime",
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"_last_modified": {
|
||||||
|
"format": "dateOptionalTime",
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"start": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var sample_data = {
|
||||||
|
"_shards": {
|
||||||
|
"failed": 0,
|
||||||
|
"successful": 5,
|
||||||
|
"total": 5
|
||||||
|
},
|
||||||
|
"hits": {
|
||||||
|
"hits": [
|
||||||
|
{
|
||||||
|
"_id": "u3rpLyuFS3yLNXrtxWkMwg",
|
||||||
|
"_index": "hypernotes",
|
||||||
|
"_score": 1.0,
|
||||||
|
"_source": {
|
||||||
|
"_created": "2012-02-24T17:53:57.286Z",
|
||||||
|
"_last_modified": "2012-02-24T17:53:57.286Z",
|
||||||
|
"owner": "tester",
|
||||||
|
"title": "Note 1"
|
||||||
|
},
|
||||||
|
"_type": "note"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "n7JMkFOHSASJCVTXgcpqkA",
|
||||||
|
"_index": "hypernotes",
|
||||||
|
"_score": 1.0,
|
||||||
|
"_source": {
|
||||||
|
"_created": "2012-02-24T17:53:57.290Z",
|
||||||
|
"_last_modified": "2012-02-24T17:53:57.290Z",
|
||||||
|
"owner": "tester",
|
||||||
|
"title": "Note 3"
|
||||||
|
},
|
||||||
|
"_type": "note"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "g7UMA55gTJijvsB3dFitzw",
|
||||||
|
"_index": "hypernotes",
|
||||||
|
"_score": 1.0,
|
||||||
|
"_source": {
|
||||||
|
"_created": "2012-02-24T17:53:57.289Z",
|
||||||
|
"_last_modified": "2012-02-24T17:53:57.289Z",
|
||||||
|
"owner": "tester",
|
||||||
|
"title": "Note 2"
|
||||||
|
},
|
||||||
|
"_type": "note"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"max_score": 1.0,
|
||||||
|
"total": 3
|
||||||
|
},
|
||||||
|
"timed_out": false,
|
||||||
|
"took": 2
|
||||||
|
};
|
||||||
|
|
||||||
|
test("ElasticSearch", function() {
|
||||||
|
var dataset = new recline.Model.Dataset({
|
||||||
|
url: 'https://localhost:9200/my-es-db/my-es-type'
|
||||||
|
},
|
||||||
|
'elasticsearch'
|
||||||
|
);
|
||||||
|
|
||||||
|
var stub = sinon.stub($, 'ajax', function(options) {
|
||||||
|
if (options.url.indexOf('_mapping') != -1) {
|
||||||
|
return {
|
||||||
|
done: function(callback) {
|
||||||
|
callback(mapping_data);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
fail: function() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
done: function(callback) {
|
||||||
|
callback(sample_data);
|
||||||
|
},
|
||||||
|
fail: function() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dataset.fetch().then(function(dataset) {
|
||||||
|
deepEqual(['_created', '_last_modified', 'end', 'owner', 'start', 'title'], _.pluck(dataset.fields.toJSON(), 'id'));
|
||||||
|
dataset.query().then(function(docList) {
|
||||||
|
equal(3, dataset.docCount);
|
||||||
|
equal(3, docList.length);
|
||||||
|
equal('Note 1', docList.models[0].get('title'));
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$.ajax.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
})(this.jQuery);
|
||||||
@@ -23,7 +23,9 @@
|
|||||||
<script type="text/javascript" src="../src/backend/webstore.js"></script>
|
<script type="text/javascript" src="../src/backend/webstore.js"></script>
|
||||||
<script type="text/javascript" src="../src/backend/dataproxy.js"></script>
|
<script type="text/javascript" src="../src/backend/dataproxy.js"></script>
|
||||||
<script type="text/javascript" src="../src/backend/gdocs.js"></script>
|
<script type="text/javascript" src="../src/backend/gdocs.js"></script>
|
||||||
|
<script type="text/javascript" src="../src/backend/elasticsearch.js"></script>
|
||||||
<script type="text/javascript" src="backend.test.js"></script>
|
<script type="text/javascript" src="backend.test.js"></script>
|
||||||
|
<script type="text/javascript" src="backend.elasticsearch.test.js"></script>
|
||||||
<script type="text/javascript" src="../src/view.js"></script>
|
<script type="text/javascript" src="../src/view.js"></script>
|
||||||
<script type="text/javascript" src="../src/view-grid.js"></script>
|
<script type="text/javascript" src="../src/view-grid.js"></script>
|
||||||
<script type="text/javascript" src="../src/view-transform-dialog.js"></script>
|
<script type="text/javascript" src="../src/view-transform-dialog.js"></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user