Сортировка результатов

Поведение сортировки в Tom Select определяет порядок отображения найденных элементов в выпадающем списке и напрямую влияет на восприятие качества поиска. В отличие от простого рендеринга массива, библиотека комбинирует несколько уровней ранжирования: результат поиска, приоритет совпадений и пользовательскую логику сортировки.

Сортировка применяется уже после того, как механизм поиска сформировал набор подходящих опций. Это означает, что сначала происходит фильтрация и оценка релевантности, затем — упорядочивание.


Базовая модель сортировки

По умолчанию Tom Select использует встроенную сортировку, ориентированную на релевантность:

  • более точные совпадения поднимаются выше;
  • совпадения в начале строки получают приоритет;
  • результаты с более высокой «оценкой совпадения» (score) отображаются первыми.

Внутренне это связано с механизмом ранжирования поиска, где каждая опция получает числовую оценку. Чем ниже значение score, тем выше приоритет.


Параметр sortField

Основной способ управления сортировкой — параметр sortField. Он определяет, по каким полям объекта данных и в каком порядке будет выполняться сортировка после поиска.

Простейшая форма

new TomSelect("#select", {
  sortField: "text"
});

В этом случае сортировка происходит по строковому полю text.


Множественные критерии сортировки

Можно задавать несколько правил сортировки, формируя цепочку приоритетов:

new TomSelect("#select", {
  sortField: [
    { field: "priority", direction: "desc" },
    { field: "text", direction: "asc" }
  ]
});

Здесь:

  • priority сортируется по убыванию;
  • при равных значениях применяется лексикографическая сортировка по text.

Такой подход позволяет реализовывать сложные сценарии, например:

  • закреплённые элементы сверху;
  • приоритетные категории;
  • пользовательские рейтинги.

Направление сортировки

Параметр direction принимает значения:

  • "asc" — по возрастанию;
  • "desc" — по убыванию.

При числовых полях это влияет на порядок приоритетов, при строковых — на алфавитный порядок.


Связь сортировки и поиска

Важный аспект поведения Tom Select — сортировка не заменяет поиск, а работает поверх него.

Алгоритм можно представить так:

  1. Формируется список кандидатов (фильтрация по вводу пользователя).
  2. Каждому элементу назначается score релевантности.
  3. Применяется sortField или пользовательская сортировка.
  4. Результат отображается в dropdown.

Если пользовательская сортировка конфликтует с релевантностью поиска, приоритет обычно остаётся за механизмом scoring.


Отключение стандартной сортировки

В некоторых сценариях требуется полностью контролировать порядок элементов. Для этого можно отключить встроенную сортировку, возвращая неизменённый порядок данных.

new TomSelect("#select", {
  sortField: null
});

или через пустой массив:

new TomSelect("#select", {
  sortField: []
});

Это полезно, когда:

  • порядок задаётся сервером;
  • используется кастомная логика отображения;
  • требуется стабильный индексный порядок.

Пользовательская функция сортировки

Для максимального контроля используется sortFn (или аналогичная пользовательская функция сортировки, в зависимости от версии и конфигурации).

Пример кастомной сортировки

new TomSelect("#select", {
  sortField: {
    field: "text",
    sort: function(a, b) {
      return a.text.length - b.text.length;
    }
  }
});

В этом примере элементы сортируются по длине строки:

  • короткие значения отображаются выше;
  • длинные — ниже.

Сортировка с учётом поиска

При кастомной сортировке важно учитывать результат поиска. Каждый элемент может содержать метаданные, включая score:

sort: function(a, b) {
  if (a.score !== b.score) {
    return a.score - b.score;
  }
  return a.text.localeCompare(b.text);
}

Такой подход сохраняет релевантность поиска и добавляет вторичный критерий.


Работа с score и влиянием релевантности

Tom Select использует внутреннюю систему оценки совпадений. Каждая опция получает score, зависящий от:

  • точного совпадения;
  • совпадения префикса;
  • наличия подстроки;
  • расстояния между символами (fuzzy matching).

Чем лучше совпадение, тем выше позиция элемента до применения дополнительной сортировки.

Важно учитывать, что принудительная сортировка может «сломать» релевантность, если полностью игнорировать score.


Сортировка и группы (optgroup)

При использовании групп (optgroup) сортировка имеет два уровня:

  1. сортировка групп;
  2. сортировка элементов внутри групп.

Сортировка групп

new TomSelect("#select", {
  optgroupField: "category",
  sortField: [
    { field: "category", direction: "asc" },
    { field: "text", direction: "asc" }
  ]
});

Здесь сначала упорядочиваются группы, затем элементы внутри них.


Поведение при удалённой (remote) загрузке

При использовании AJAX или динамической подгрузки данных сервер может возвращать уже отсортированный список. В этом случае локальная сортировка может быть избыточной.

Типичный сценарий:

new TomSelect("#select", {
  load: function(query, callback) {
    fetch(`/search?q=${query}`)
      .then(res => res.json())
      .then(data => callback(data.items));
  },
  sortField: null
});

Сервер полностью контролирует порядок, клиент только отображает результат.


Стабильность сортировки

При одинаковых значениях ключей сортировки поведение может зависеть от реализации JavaScript-движка. Для обеспечения стабильности добавляется вторичный критерий:

  • индекс элемента;
  • уникальный id;
  • текстовое поле.
sort: function(a, b) {
  if (a.text === b.text) {
    return a.id - b.id;
  }
  return a.text.localeCompare(b.text);
}

Производительность сортировки

При большом количестве элементов сортировка становится значимым фактором производительности.

Основные рекомендации по оптимизации:

  • избегать сложных вычислений внутри sort;
  • минимизировать количество полей сортировки;
  • использовать предварительно рассчитанные значения (например, priority);
  • отдавать предпочтение серверной сортировке при больших объёмах данных.

Особенно критично это при использовании fuzzy search, где уже на этапе поиска выполняются вычислительные операции.


Комбинирование сортировки и кастомного рендера

Сортировка влияет только на порядок элементов, но не на их визуальное представление. При кастомном рендеринге важно не смешивать визуальные метки с логикой сортировки.

new TomSelect("#select", {
  sortField: [
    { field: "priority", direction: "desc" }
  ],
  render: {
    option: function(data) {
      return `<div>${data.text}</div>`;
    }
  }
});

Сортировка остаётся независимой от HTML-структуры.


Типичные ошибки при настройке сортировки

На практике часто встречаются следующие проблемы:

  • полное игнорирование score приводит к нерелевантным результатам поиска;
  • использование строковой сортировки для числовых полей;
  • отсутствие вторичного ключа сортировки;
  • попытка сортировать внутри render вместо sortField;
  • конфликт серверной и клиентской сортировки.

Корректная архитектура предполагает чёткое разделение:

  • сервер — формирует данные;
  • Tom Select — ранжирует и отображает;
  • sortField — задаёт правила локального упорядочивания.