backbone-db-elasticsearch
Advanced tools
Comparing version 0.0.2 to 0.1.0
181
index.js
@@ -11,2 +11,3 @@ var _ = require('lodash'); | ||
this.client = client; | ||
this.prefixSeparator = '::'; | ||
} | ||
@@ -16,31 +17,6 @@ | ||
var getESOptions = function(model, options) { | ||
if (!_.isObject(model.searchOptions)) throw new Error('searchOptions must be defined'); | ||
if (!model.id) throw new Error('Model.id must be defined'); | ||
if (!model.type) throw new Error('Model.type must be defined'); | ||
options = options || {}; | ||
var esData = { | ||
index: model.searchOptions.index, | ||
type: model.type, | ||
}; | ||
esData.id = model.id.toString(); | ||
if (options.includeBody) { | ||
if (!_.isFunction(model.searchValues)) { | ||
throw new Error('searchValues function must be defined'); | ||
} | ||
if (options.update) { | ||
esData.body = { | ||
doc: model.searchValues() | ||
}; | ||
} else { | ||
esData.body = model.searchValues(); | ||
} | ||
} | ||
return esData; | ||
}; | ||
var convertResults = function(hits) { | ||
if (!hits || !hits.length) return []; | ||
return _.map(hits, function(hit) { | ||
debug('convert', hit); | ||
var doc = {}; | ||
@@ -52,2 +28,3 @@ // prefix ids with type because otherwise collection may have colliding ids | ||
doc.content_type = hit._type; | ||
doc.score = hit._score; | ||
return doc; | ||
@@ -57,9 +34,22 @@ }); | ||
var convertMsearchResults = function(responses) { | ||
if (!responses || !responses.length) return []; | ||
var results = []; | ||
_.each(responses, function(resp) { | ||
var hits = convertResults(resp.hits.hits); | ||
results = results.concat(hits); | ||
}); | ||
return results; | ||
}; | ||
_.extend(ElasticSearchDb.prototype, Db.prototype, { | ||
create: function(model, options, callback) { | ||
var self = this; | ||
this.client.create(getESOptions(model, { | ||
var searchObject = this.getESOptions(model, { | ||
includeBody: true | ||
}), function(error, resp) { | ||
}); | ||
debug('create', searchObject); | ||
this.client.create(searchObject, function(error, resp) { | ||
if (options.wait === true) { | ||
debug('refresh indices'); | ||
self._refreshIndices(null, function(err, res) { | ||
@@ -75,3 +65,3 @@ callback(error, model.toJSON()); | ||
find: function(model, options, callback) { | ||
this.client.get(getESOptions(model), function(error, resp) { | ||
this.client.get(this.getESOptions(model), function(error, resp) { | ||
if (error) return callback(error); | ||
@@ -84,2 +74,39 @@ model.set(resp._source); | ||
findAll: function(collection, options, callback) { | ||
if (options.msearch) { | ||
return this.msearch(collection, options, callback); | ||
} else { | ||
return this.search(collection, options, callback); | ||
} | ||
}, | ||
update: function(model, options, callback) { | ||
options = options || {}; | ||
if (!options.update) return this.create.apply(this, arguments); | ||
this.client.update(this.getESOptions(model, { | ||
includeBody: true, | ||
update: true | ||
}), function(error, resp) { | ||
callback(error, model.toJSON()); | ||
}); | ||
}, | ||
destroy: function(model, options, callback) { | ||
var searchObject = this.getESOptions(model); | ||
debug('destroy', searchObject); | ||
this.client.delete(searchObject, function(error, resp) { | ||
callback(error, model.toJSON()); | ||
}); | ||
}, | ||
// Private methods: | ||
_refreshIndices: function(indexes, callback) { | ||
if (!indexes) indexes = '_all'; | ||
this.client.indices.refresh({ | ||
index: indexes | ||
}, function(err, response) { | ||
callback(err); | ||
}); | ||
}, | ||
search: function(collection, options, callback) { | ||
var query = { | ||
@@ -90,3 +117,5 @@ body: { | ||
}; | ||
if (options.index) query.index = options.index; | ||
if (options.index) { | ||
query.indexes = this.prefixIndexKeys(options.index); | ||
} | ||
if (options.type) query.type = options.type; | ||
@@ -101,6 +130,8 @@ | ||
if (options.filter) query.body.filter = options.filter; | ||
if (options.indicesBoost) query.body.indicesBoost = options.indicesBoost; | ||
if (options.indicesBoost) { | ||
query.body.indicesBoost = this.prefixObjectIndexKeys(options.indicesBoost); | ||
} | ||
if (options.sort) query.body.sort = options.sort; | ||
debug('findAll query', query); | ||
debug('findAll query', JSON.stringify(query)); | ||
this.client.search(query, function(error, resp) { | ||
@@ -113,30 +144,76 @@ if (error) return callback(error); | ||
update: function(model, options, callback) { | ||
options = options || {}; | ||
if (!options.update) return this.create.apply(this, arguments); | ||
this.client.update(getESOptions(model, { | ||
includeBody: true, | ||
update: true | ||
}), function(error, resp) { | ||
callback(error, model.toJSON()); | ||
msearch: function(collection, options, callback) { | ||
var query = { | ||
body: this.prefixMqueryOptions(options.body) | ||
}; | ||
debug('mquery:', query); | ||
this.client.msearch(query, function(error, resp) { | ||
if (error) return callback(error); | ||
var responseErrors = _.filter(resp.responses, function(response) { | ||
return response.error; | ||
}); | ||
if (responseErrors.length) { | ||
var msg = _.pluck(responseErrors, 'error').join(' & '); | ||
return callback(new Error(msg)); | ||
} | ||
callback(null, convertMsearchResults(resp.responses)); | ||
}); | ||
}, | ||
destroy: function(model, options, callback) { | ||
this.client.delete(getESOptions(model), function(error, resp) { | ||
callback(error, model.toJSON()); | ||
}); | ||
getESOptions: function(model, options) { | ||
if (!_.isObject(model.searchOptions)) throw new Error('searchOptions must be defined'); | ||
if (!model.id) throw new Error('Model.id must be defined'); | ||
if (!model.type) throw new Error('Model.type must be defined'); | ||
options = options || {}; | ||
var esData = { | ||
index: this.name + this.prefixSeparator + model.searchOptions.index, | ||
type: model.type, | ||
}; | ||
esData.id = model.id.toString(); | ||
if (options.includeBody) { | ||
if (!_.isFunction(model.searchValues)) { | ||
throw new Error('searchValues function must be defined'); | ||
} | ||
if (options.update) { | ||
esData.body = { | ||
doc: model.searchValues() | ||
}; | ||
} else { | ||
esData.body = model.searchValues(); | ||
} | ||
} | ||
return esData; | ||
}, | ||
// Private methods: | ||
_refreshIndices: function(indexes, callback) { | ||
if (!indexes) indexes = '_all'; | ||
this.client.indices.refresh({ | ||
index: indexes | ||
}, function(err, response) { | ||
callback(err); | ||
}); | ||
// prefix keys when index is a comma separated list | ||
prefixIndexKeys: function(index) { | ||
var indexes = index.split(','); | ||
return _.map(indexes, function(index) { | ||
return this.name + this.prefixSeparator + index; | ||
}, this).join(','); | ||
}, | ||
// prefix keys when a Object type option is given | ||
// e.g. {indexa: 123, indexb: 455} | ||
prefixObjectIndexKeys: function(indexObject) { | ||
var prefixed = {}; | ||
for (var key in indexObject) { | ||
prefixed[this.name + this.prefixSeparator + indexObject[key]]; | ||
} | ||
return prefixed; | ||
}, | ||
prefixMqueryOptions: function(mqueryBody) { | ||
var result = []; | ||
_.each(mqueryBody, function(opts) { | ||
var options = _.clone(opts); | ||
if (options.index) options.index = this.prefixIndexKeys(options.index); | ||
result.push(options); | ||
}, this); | ||
return result; | ||
} | ||
}); | ||
module.exports = ElasticSearchDb; |
{ | ||
"name": "backbone-db-elasticsearch", | ||
"version": "0.0.2", | ||
"version": "0.1.0", | ||
"description": "Elasticsearch driver for backbone-db", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -107,4 +107,8 @@ ## backbone-db-elasticsearch | ||
#### msearch | ||
If set to true, do a [multi search](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-multi-search.html) | ||
## Notes | ||
This adapter is not fully backbone-db compliant, since query DSL is using Elasticsearch syntax, instead of MongoDB syntax. |
@@ -205,2 +205,29 @@ require('mocha-as-promised')(); | ||
}); | ||
describe('Multi search', function() { | ||
it('should do a msearch', function() { | ||
var queriesBody = [ | ||
// match all query | ||
{ index: 'anotheridx'}, | ||
{ query: { match_all: {} } }, | ||
// query_string query, on index/type | ||
{ index: 'testidx', type: 'test' }, | ||
{ | ||
query: { | ||
query_string: { query: '"abc"' } | ||
}, | ||
size: 1 | ||
} | ||
]; | ||
collection = new this.Collection(); | ||
return collection | ||
.fetch({ | ||
msearch: true, | ||
body: queriesBody | ||
}) | ||
.then(function() { | ||
collection.length.should.equal(2); | ||
}); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23004
531
113