在我的 Angular (1.3) 应用程序中,我使用的是JSData (2.0.0),我想使用Lunr为这些资源添加全文搜索功能,而无需 Ajax。有小费吗?
问问题
769 次
1 回答
0
为此,我创建了SearchableDS
JSDataDS
资源的扩展。
这是一个使用示例:
angular.module("app")
.factory("User", function(SearchableDS) {
var resource;
// so far the same JSData code
resource = SearchableDS.defineResource({
name: 'user',
endpoint: 'users',
idAttribute: 'id',
searchFields: { // Lunr searchable fields and their respective boost
name: 7,
title: 3
}
});
return resource;
})
.controller(function(User) {
// first we fetch all the records
User.findAll({limit: 1000}).then(function() {
var users;
// now we can search local records
return users = User.search('tim');
});
});
SearchableDS
:
angular.module("app")
.constant('Lunr', lunr) // lunr.js
.constant('_', _) // underscore.js
.service('SearchableDS', function(DS, Lunr, _) {
_(this).extend(DS); // extending DS with new capabilites
this.defineResource = function(options) {
var addToIndex, defaultOpts, index, resource;
defaultOpts = {
searchMapper: angular.identity, // optional. a function to create objects for a different lunr mapping. useful for e.g. when the records have nested objects
searchFields: {}
};
options = _(defaultOpts).extend(options);
resource = DS.defineResource(options);
index = Lunr(function() { // create lunr index
var _this = this;
this.ref(options.idAttribute);
// add searchable fields and their boost value to the index
_(options.searchFields).each(function(boost, name) {
_this.field(name, {boost: boost})
});
});
addToIndex = function(entity) {
index.add(options.searchMapper(entity));
};
// wrap the original record-fetching methods so that they'll add newly fetched records to Lunr's index
resource.findAll = (function() {
var originalFunc;
originalFunc = resource.findAll;
return function() {
return originalFunc.apply(resource, arguments).then(function(entities) {
return _(entities).each(addToIndex); // add to lunr index
});
};
})();
resource.find = (function() {
var originalFunc;
originalFunc = resource.find;
return function() {
return originalFunc.apply(resource, arguments).then(function(entity) {
return addToIndex(entity); // add to lunr index
});
};
})();
// full text search of local records using Lunr
resource.search = function(str) {
var entities, ids;
ids = _(index.search(str)).pluck('ref'); // use Lunr only to find the record IDs
entities = _(resource.getAll())
.chain()
.filter(function(t) {
return ~ids.indexOf(t.id)
}).sortBy(function(t) {
return ids.indexOf(t.id)
})
.value();
console.log(options.name + "#search: " + entities.length + " results for '" + str + "'");
return entities;
};
return resource;
};
return this;
})
于 2015-12-24T09:38:07.333 回答