Фильтровать магистральную коллекцию на основе нескольких атрибутов модели

Я хочу отфильтровать базовую коллекцию, поэтому мне возвращаются только модели, которые соответствуют или близки к некоторым параметрам поиска,

Структура моих моделей выглядит так:

{  
    email: "[email protected]",
    first_name: "Name",
    surname: "LastName",
    handle: "NameLastName",
    initials: "NL"  
}

Вышеприведенная модель - это модель «Пользователь», она может быть в «UsersCollection», что, как я надеюсь, достижимо, заключается в поиске «UsersCollection» для моделей на основе адреса электронной почты, имени, фамилии и дескриптора, в момент, я могу искать только по одному атрибуту, ниже функция поиска из "UsersCollection",

search : function(letters){
    if(letters == "") return this;

    var pattern = new RegExp(letters,"gi");
    return _(this.filter(function(data) {
        return pattern.test(data.get("first_name"));
    }));
}

Параметр Letters берется из представления и является значением ввода текста. Теперь это работает, но создает совпадения только на основе first_name, как я могу сопоставить несколько атрибутов?


person Cycs    schedule 30.07.2014    source источник
comment
Очень похоже на stackoverflow.com/questions/24866200/   -  person nikoshr    schedule 30.07.2014


Ответы (3)


теперь он вернет модели, соответствующие любому из атрибутов.

  var UsersCollection = Backbone.Collection.extend({
      model: User,

      myFilter: function( email, first_name, surname , handle) {
        filtered = this.filter(function(user) {
          return user.get("email") === email || user.get("first_name") === first_name ||
                 user.get("surname") === surname || user.get("handle") == handle ;
          });
        return new UsersCollection(filtered);
      }

    });

    var filterdMe = UsersCollection.myFilter("[email protected]","something1","something2","something3");
person StateLess    schedule 31.07.2014
comment
Будет ли это возвращать true, даже если 2 из 3 атрибутов не совпадают? - person Cycs; 31.07.2014
comment
Ах да, спасибо. Мне нужно что-то, что мы работаем на основе атрибута за атрибутом, если это не соответствует этому, попробуйте следующий атрибут и т. д. - person Cycs; 31.07.2014
comment
Вы можете проверить это и ответить, это то, что вы ищете? - person StateLess; 31.07.2014
comment
Я сделаю в ближайшее время, как раз в середине кодирования календаря в данный момент. - person Cycs; 31.07.2014

Я тоже делаю что-то подобное. Я сопоставляю атрибут input с ключом модели и передаю объект search, который имеет атрибуты, которые ищет пользователь. Функция search выглядит примерно так: Вот минимальная демонстрация jsbin.

var Collection = Backbone.Collection.extend({
  model:yourModel,

  search:function(find) {
    return this.filter(function(model) {
      var json = model.toJSON();

      for (var k in find) {
        var re = new RegExp(find[k],"i");
        if (json[k].search(re) === -1) return false;
      }

      return true;
    });

   }
});

HTML-код выглядит так:

<input name="first_name"/>
<input name="last_name"/>
<input name="email"/>

Код просмотра будет (более или менее):

var View = Backbone.View.extend({
  template:_.template($('#view-template').html()),
  events: {
    'keyup input' : 'search'
  },

  search:function() {
    var find = {};

    this.$('input').each(function() {
      var $element = $(this),
          modelKey = $element.attr('name'),
          modelVal = $element.val();
      find[modelKey] = modelVal;
    });

    var results = this.collection.search(find);

    /* do something with results */

  }
});

Кажется, это работает прилично, если у вас нет большого набора данных. Вы также можете использовать indexOf и toLowerCase, если не хотите использовать объект RegExp. Может быть, это поможет вам начать какой-то путь.

person fbynite    schedule 01.08.2014

Я знаю, что это старо. Сегодня я решил то же самое и подумал, что должен опубликовать код, который я использую. Я нашел многое из этого из другого вопроса stackoverflow. Я не могу найти его сейчас, извините!

Это создаст новый массив из базовой коллекции. Если вам нужна другая основная коллекция, вы можете сделать new BackboneCollection(search_results);.

var search_results = this.collection.filter(function(model) {
  return _.some(model.attributes, function(val, attr) {

    if(val !== null && val !==  undefined)
    {
      if(!_.isString(val))
      //if a model's attribute is a number, we make it a string.
      {
        val = val.toString();
      }
      //convert both options to uppercase for better searching ;)
      val = val.toUpperCase();
      q = q.toUpperCase(); //q is the search term, I grabbed it using JQuery

      var array = q.split(" ");
      return ~val.indexOf(q);
    }
    else
    {
      return false;
    }

  });
});

Примечание. Это не будет работать для нескольких слов. Если бы вы искали автомобили, вам бы подошёл Volkswagen, но не Volkswagen 1988 года, если только один из атрибутов модели не был «Volkswagen 1988 года», но, скорее всего, это были бы два разных атрибута (год и марка).

person Andrew Crawford    schedule 27.11.2015