在嵌套对象中搜索文本(Backbone.js集合作为示例)

我有一个backbone.js集合,我需要在其上进行全文搜索。 我手头的工具如下:

Backbone.js,underscore.js,jQuery

对于那些不熟悉骨干的人:

骨干集合只是一个对象。 在集合内部有一个带模型的数组。 每个模型都有一个包含属性的数组。 我必须在每个属性中搜索字符串。

我用的代码是:

query = 'some user input'; query = $.trim(query); query = query.replace(/ /gi, '|'); var pattern = new RegExp(query, "i"); // this.collection.forEach is the same as _.each // only it get's the models from the collection this.collection.forEach(function(model) { var check = true; _.each(model.attributes, function(attr){ if(pattern.test(attr) && check){ // Do something with the matched item check = false; } }, this); }, this); 

也许我正在使用的工具之一有更好的方法来解决这个问题?

Backbone将许多下划线方法扩展到Collection类中,因此您可以摆脱其中的一些内容。 真的,你可能想在集合本身作为一种方法来实现这个,然后我可能会使用一个很好的老式for循环看看那些键,特别是如果我想要突破它。

 // in Backbone.Collection.extend search: function( query, callback ){ var pattern = new RegExp( $.trim( query ).replace( / /gi, '|' ), "i"); var collection = this; collection.each(function(model) { for( k in model.attributes ){ if( model.attributes.hasOwnProperty(k) && pattern.test(model.attributes[k]) ){ callback.call( collection, model, k ); break; // ends the for loop. } } }); } // later collection.search('foo', function( model, attr ){ console.log('found foo in '+model.cid+' attribute '+attr); }); 

也就是说,这只会从集合中返回第一场比赛。 您可能更喜欢将结果数组作为[model,attribute]对返回的实现。

 // in Backbone.Collection.extend search: function( query, callback ){ var matches = []; var pattern = new RegExp( $.trim( query ).replace( / /gi, '|' ), "i"); this.each(function(model) { for( k in model.attributes ){ if( model.attributes.hasOwnProperty(k) && pattern.test(model.attributes[k]) ){ matches.push([model, k]); } } }); callback.call( this, matches ); } // later collection.search('foo', function( matches ){ _.each(matches, function(match){ console.log('found foo in '+match[0].cid+' attribute '+match[1]); }); }); 

或者,如果您想要匹配但不关心匹配哪个属性的模型数组,则可以使用filter

 // in Backbone.Collection.extend search: function( query, callback ){ var pattern = new RegExp( $.trim( query ).replace( / /gi, '|' ), "i"); callback.call( this, this.filter(function( model ){ for( k in model.attributes ){ if( model.attributes.hasOwnProperty(k) && pattern.test(k) ) return true; } })); } // later collection.search('foo', function( matches ){ _.each(matches, function(match){ console.log('found foo in '+match[0].cid+' somewhere'); }); }); 

你的内心each都在短路,所以你可以切换到_.any()而不是你的_.each()和一个标志组合; 一旦回调函数返回trueany停止迭代,并且如果可用,也委托给本机some方法。

 this.collection.each(function(model) { _(model.attributes).any(function(attr, key) { if(!pattern.test(attr)) return false; // Do something with the matched item... return true; }); }); 

我也删除了this参数的上下文,因为你没有在任何地方使用this ,如果“做某事”需要它们你可以把它们放回去。

如果简单的正则表达式搜索不够好,您可以查看集合的词干和反向索引。