4

全文検索を実行する必要がある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);

たぶん私が使用しているツールの1つはこれに対処するためのより良い方法を持っていますか?

4

2 に答える 2

4

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);
});

とは言うものの、これはコレクションから最初の一致を返すだけです。結果の配列を[モデル、属性]のペアとして返す実装をお勧めします。

// 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');
  });
});
于 2012-05-06T04:49:53.490 に答える
2

あなたのインナーeachは短絡を引き起こしているので、あなたとフラグの組み合わせの_.any()代わりに切り替えることができます。コールバック関数が戻るとすぐに反復を停止し、可能な場合はネイティブメソッドに委任します。_.each()anytruesome

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ました。「何かをする」必要がある場合は、コンテキスト引数を元に戻すことができます。

単純な正規表現検索では不十分な場合は、コレクションのステミングと逆インデックスを調べることができます。

于 2012-05-06T04:51:07.443 に答える