2017-02-04 12 views
1

У меня есть большой список строк (содержит имена пользователей, около 350 тыс. Записей). Мне нужно сохранить его отсортированным по лексикографическому порядку, и он должен иметь возможность эффективно извлекать существование членов * и членство **. Сортированные наборы Redis выглядят как тип данных для задания.Случайное лексикографическое упорядочение в отсортированном наборе redis

Однако я, кажется, падаю на первое препятствие. В частности, одним из моих ключевых требований является совместное сохранение разных букв, если они начинаются с одной и той же буквы. Например. как Bender, так и bender должны быть заказаны бок о бок. Однако сортированные наборы redis строги в соответствии с правилами лексикографического упорядочения, поэтому все строки, начинающиеся с верхнего регистра, сортируются по умолчанию до того, как все строки начинаются с нижнего регистра (например, Z заказано до a, но после A).

Есть ли способ, которым я могу обойти это и по-прежнему использовать отсортированные наборы redis для выполнения моих требований? FYI, я использую redis версии 2.8.4. Заранее спасибо.


* Член существование: с учетом именем пользователя, проверить, существует ли уже он в сохраненном наборе

** подобии члена: дало имя пользователя, подтяните г N сохраненных имена пользователей, которые больше всего нравится данный пользователь

+2

См. [Нормализация строк для случая и акцентов] (https://redis.io/topics/indexes#normalizing-strings-for-case-and-accents) – thepirat000

+0

@ thepirat000: это отличный пост. Только проблема заключается в использовании ZRANGEBYLEX, который недоступен для redis 2.8.4. Я могу реализовать более раннюю версию: http://oldblog.antirez.com/post/autocomplete-with-redis.html, за исключением того, что это не лексикографически агностик. –

ответ

1

Вам нужно сделать специальную кодировку с именами. Ниже приведен пример.

Предположим, что длина всех имен меньше 100 символов. Для каждого имени, выполните следующие шаги, чтобы кодировать его:

  1. записи индексов заглавных букв с 2 цифрами: для BeNd, индексы являются 00 и 02.
  2. преобразовать заглавные буквы имени, в строчные, чтобы получить более низкое имя случая: от BeNd к bend
  3. добавить индексы к нижнему имени случая, чтобы получить encoded name: от bend к bend0002
  4. добавить encoded name в отсортированном наборе: zadd key 0 bend0002

Таким образом, BeNd и bend должны быть заказаны бок о бок.

Если вы хотите выполнить поиск, используйте тот же метод кодирования, чтобы закодировать данное имя, выполнить поиск и декодировать результаты. Поскольку encoded name записывает индексы букв верхнего регистра, вы можете легко декодировать их.

+0

Умный. Что произойдет, если строка имени пользователя содержит конечные 0s, например, например. представьте себе имя пользователя «Bender12300», например? –

+0

@HassanBaig использует специальный символ, который НЕ существует ни в одном имени пользователя, как разделитель между наименьшим именем и индексами.Например: используйте '-' в качестве разделителя и закодируйте' Bender12300' как 'bender12300-00' –

+0

@for_stack: Вышеупомянутое решение будет работать и для нечувствительного к регистру поиска? –