Как стать автором
Обновить

Комментарии 66

Чем вам elasticsearch не подошел в качестве поисковика?
На самом деле просто не знал про него. Да и не сильно искал. Просто хотелось самостоятельно разобраться в этом вопросе.
Я так и не понял, что вы сделали и зачем (а картинка из заключения — её вообще лучше убрать).

Детально описаны какие-то тривиальные вещи, а про остальное просто сказали, что оно есть.

Для «юнного программиста» старт хороший и у вас всё получится и проект вам ещё пригодится.

Проект «абсолютно открытый», а где ссылка?
Веб-часть вот. У приложения на андроиде пришлось закрыть исходники по просьбе Abbyy. Да и в приложении нет ничего особого.
И да. Мне стыдно за этот код. По хорошему надо бы всё переписать, но у меня нет времени, да и проект заморожен до лучших времен.

По поводу сути — хотел облегчить страдания библиотекарям. Занести все книги в БД (описание, название, местоположение, кто и когда брал) с помощью мобильного приложения (фотографируешь книгу, isbn, корешок или вводишь вручную). По всему этому сделать поиск + низкая стоимость.

И да. Первый мой пост все же. Много косяков заметил уже после публикации. Буду иметь ввиду. Спасибо за комментарий.
> И да. Мне стыдно за этот код.

Значит вы хороший программист :)
Make it Work, Make it Right, Make it Fast.

> По поводу сути…

Теперь яснее. А то интерфейсы и логотип как бы намекают, что это для широкой аудитории (тоесть, посетителей библиотеки) и картинка в голове не складывалась.

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


Первое правило в работе с безопасностью: никогда не изобретать свою систему безопасности.
Проект, в первую очередь, создавался для собственного развития и опыта.

Это не повод вставлять в него собственную систему аутентификации/авторизации.


Если вам интересно поэкспериментировать с криптографией — есть курсы и тестовые задания. В проектах, которые выпускаются в реальную жизнь, надо использовать стандартные компоненты — тогда бы вам не пришлось придумывать собственную систему проверки подлинности сервера (которая, по вашему описанию, полностью подвержена MitM-атаке).

Самая главная причина такого решения — я захотел. Всё остально второстепенно. Не забывайте, что это не коммерческий продукт, а школьный проект.
Самая главная причина такого решения — я захотел


"Я захотел" совершить ошибку, совершил ее, и исправлять не буду. Так это сейчас выглядит.
Не забывайте, что это не коммерческий продукт, а школьный проект.


Это повод делать его плохо?
Это повод делать так, чтобы было интересно и полезно, в первую очередь, мне. Естественно, в будущем велосипедов постараюсь избежать.
Это повод делать так, чтобы было интересно и полезно, в первую очередь, мне.


На безопасность тех, кто пользуется вашей программой, вам наплевать?
В случае школьного проекта, да. В таком виде, всеравно в продакшн пускать это не буду. По хорошему это всё надо переписать.
PHP — старая технология и неполноценный язык. Поэтому я выбрал рельсы.


Закрыл статью, дальше не читал.
Это я опрометчиво такую фразу оставил :) Давайте не будем разжигать конфликт по этому поводу. Признаю свою вину в этом вопросе.
НЛО прилетело и опубликовало эту надпись здесь
Что с ним?
Ну… его нет. RoR — набор слабосвязанных библиотек, которые вместе образуют фреймворк. Как в наборе библиотек вычленить ядро? И что это за ядро вообще такое, что оно делает, чем занимается?
*ядро Ruby
Говорят, к концу 2016 года Матц обещал выпустить двухядерный Ruby…
А потом ещё и ядра с Hyper-Threading, итого 4 ядра! Уииии…
Дня старта не плохо, НО, если выбираете ruby и RoR в частности, то пользуйтесь всеми возможностями экосистемы и накопленными решениями:
— авторизация devise + Doorkeeper (OAuth2 server)
— хотите токены с проверкой, используйте JWT
— поиск, тут да elastic
Спасибо :) В будущем постараюсь исключить велосипеды.
Странно, в районной библиотеке, которой я пользовался 15 лет назад, стояли, конечно, старенькие по тем временам компы, но они позволяли очень гибко искать книги и определять их наличие в конкретный момент времени… И библиотека — не имени маяковского какая-нибудь со штрих-кодами на всем, а обычная…
Такого в моей школьной библиотеке нет. Да и простота установки такой системы и способ заполнения её данными ставиться под вопросом.
А сейчас все школьники такие умные?!
Мы притворяемся. Все нормально.
ROR — лучший выбор школоты. любят они языки типа руби — непонятные и с кучей синтаксического сахара, любят манкипатчить код.

> PHP — старая технология
ололо

http://php.net/

Эта тема обсуждалась ни один раз. Давайте не будем поднимать это снова, хорошо?
Понятно, что код в мусорку. Но там в контроллере на каждый запрос поиска все книги из базы ползут в память, потом преобразуются в массив и тд тп. Никакого железа не хватит. Я про следующий код:


books = Book.all

books =
books.to_a.sort { |book1, book2| book2.getSearchIndex(params[:srch]) — book1.getSearchIndex(params[:srch]) }

Мне кажется подтормаживать должно уже на 100-500 книгах. На каких объемах гонялся код, подозрений не вызывало время ответа?
Применительно к Вашему случаю, необходимо менять подход. У Вас стратегия: тащим все в память, перебираем с некой логикой, пользуемся. А в подобных задачах желательно на этапе записи в БД составить индекс, что бы потом силами БД простым запросом вытащить нужное. Т.е. чуть дольше пишем, но потом быстро считаем. БД уже хранит данные в нужном формате. А так как операций записи сильно меньше, то получаем большой выигрыш.
Правильно выше писали, правильно было бы использовать Elasticsearch, Sphinx и подобное.
Ну и на будущее, при обработке коллекций вместо вытягивания всей таблицы и затем перебора в памяти, используем find_each. Т.е. порционно выкачиваем записи из БД.
Это элементарные вещи. Но и Вы только в начале пути, потом разум будут волновать вопросы совсем другого порядка. Удачи!
Про find_each не знал. Всё остальное знал, но я указал в статье, что индексация дает прирост производительности только на больших данных. В случае маленькой библиотеки нам нужна точность, но не важна производительность
Мало знать, нужно применять.
Правильная(читай «нормальная») архитектура окупается с лихвой уже на первых этапах жизни приложения.
Тут не выбор быстро<=>точно, тут выбор быстро<=>медленно, Вы выбрали медленно. И чем больше книг в библиотеке и активнее пользователи — тем хуже поведение системы.
Но это ладно, пишите на ruby Вы отвратительно =) И тут же набежали ruby-хейтеры, про сахар, про манкинпатчинг сразу вспомнили (я никогда в жизни не патчил, думаю я не один такой).
Например следующий код можно выбросить из экшена search, это переливание ни к чему:
@books_for_s = []
books.each do |i|
@books_for_s.push i
end

И тут уже не знаю что посоветовать, может больше чужого кода смотреть, в туториалы с примерами кода вникать, стайлгайды глянуть, типовые ошибки новичков погуглить и тд.
Какая речь может идти о индексации, если поиск нечеткий и нам надо проработать все варианты.
Посмотрите как устроена работа elasticsearch-а или sphinx-а и почему они быстро ищут (разумеется с морфологией и тд).
Там используется индексация, что приводит к ухудшению качества поиска, но к существенному увеличению скорости. О чем выше я и сказал.
Там используется индексация, что приводит к ухудшению качества поиска,


Вы это утверждение проверяли? Сама по себе индексация к ухудшению поиска не приводит, к ухудшению приводит неправильно выбранный алгоритм. Для вашего случая (поиск по совпадениям слов с фиксированным количеством ошибок, никакой морфологии), если я не ошибаюсь, можно использовать n-граммы, где n — длина слова минус два, а дальше строить индекс по этим n-граммам.

А нет, я не совсем прав. n-граммы, конечно, использовать можно, но вот формировать их сложнее. Собственно, в статье ntz алгоритмы и показаны.

Да. Я про это и говорил

Говорить-то говорили, только что-то я не вижу, чтобы вы их использовали (может, я, конечно, не туда смотрю?). Более того, вы даже не используете очевидную (из вашего требования "Если слово имеет меньше 3 ошибок, принять его за правильное") оптимизацию, основанную на длинах слов.

В коде идет 30% от длины слова и учитывается длинна слова при ранжировании поиска. Это опечатка в текста. И да. Индексацию я не использую, потомучто это медленно на малых количествах книг. О чем я и упоминал в тексте поста, ссылаясь на статью ntz.
В коде идет 30% от длины слова


Где именно?
Индексацию я не использую, потомучто это медленно на малых количествах книг.


Вы это замеряли?
О чем я и упоминал в тексте поста


Серьезно? Приведите цитату.
Вы это замеряли?

Да. Замерял. Делая индексацию, мы создаем множество слов. Поиск по индексированной базе O(logN*L). Поиск по непроиндексированной O(N*M*L). При малом N приемущества имеет поиск не по индексированной базе так как в случае индексации N пропорционально увиличиватся. На больших словарях выгодна индексация т.к. многие варианты уже обработаны.
Либо делать частичную индексацию. Но у неё точность маленькая. В данном случае производительность не критична, а вот точность важна.

Расширение выборки
Размер индекса: 65 Мб
Время поиска: 320 мс / 330 мс
Полнота результатов: 100%

N-грамм (оригинальный)
Размер индекса: 170 Мб
Время создания индекса: 32 с
Время поиска: 71 мс / 110 мс
Полнота результатов: 65%

N-грамм (модификация 1)
Размер индекса: 170 Мб
Время создания индекса: 32 с
Время поиска: 39 мс / 46 мс
Полнота результатов: 63%

N-грамм (модификация 2)
Размер индекса: 170 Мб
Время создания индекса: 32 с
Время поиска: 37 мс / 45 мс
Полнота результатов: 62%

Хеширование по сигнатуре
Размер индекса: 85 Мб
Время создания индекса: 0.6 с
Время поиска: 55 мс
Полнота результатов: 56.5%

BK-деревья
Размер индекса: 150 Мб
Время создания индекса: 120 с
Время поиска: 540 мс
Полнота результатов: 63%

Поиск по индексированной базе O(logNL). Поиск по непроиндексированной O(NM*L)


O(log N * L) меньше, чем O(NML)
Либо делать частичную индексацию. Но у неё точность маленькая


Да откуда вы это взяли? Возьмем банальнейший поиск по слову. Если у вас максимально допустимая дистанция редактирования — 2, значит, вам нужно выбрать для сравнения слова, чья длина в пределах двух от длины вашего слова. Что не так с "точностью"?

И зачем вы приводите не свои результаты?
И зачем вы приводите не свои результаты?

Потомучто вы упорно не пытаетесь разобраться в этом вопросе. Я скидывал ссылку на статью ntc. Вам было лень её прочитать. Я любезно перекопировал её вам.

O(log N * L) меньше, чем O(NML)


N разное.

Что не так с «точностью»?


Попробуйте посмотреть на ту цитату, которую я скидывал

P.S. Я заканчиваю этот разговор со своей стороны. Я подозреваю, что вы просто тролль и даже не пытаетесь выяснить правду в данном вопросе.
Потомучто вы упорно не пытаетесь разобраться в этом вопросе. Я скидывал ссылку на статью ntc. Вам было лень её прочитать. Я любезно перекопировал её вам.


У вас свои замеры, подтверждающие ваши утверждения, есть?
N разное.


Значит, приводить эти две метрики рядом — нельзя.
Попробуйте посмотреть на ту цитату, которую я скидывал


И какое отношение она имеет к приведенной мной методике?
У вас так же откровенно не корректный способ ранжирования результатов. Делать +1 на каждое последующее «не полное» совпадение значит почти стопроцентное перемешивание результатов где есть более важные ключевые слова и в тоже время куча второстепенных и малозначимых.
А ну это да. Это косяк. Я бы исправил в будующих обновлениях
Мы тут с golang программистами в чате твою статью пообсуждали, не хочешь попробовать Golang в качестве замены RoR?
Мысль хорошая. В следующий раз попробую Golang

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

И что? Ещё раз! Я отказываюсь использовать готовые библиотеки на поиск в данном проекте!
И что?


И то, что можно воспользоваться опытом.
Я отказываюсь использовать готовые библиотеки на поиск в данном проекте!


Угу. Мне ваша фраза "использование готовых решений полностью отметается по причине того, что все крупные поисковики требуют соединения с интернетом" с самого начала казалась лукавством, а теперь вы это сомнение подтвердили.
В этой фразе я имел ввиду поисковики типа Гугла и Яндекса.

"готовые решения" ими не ограничиваются.

Ну это да.
Тоже правильно. На собеседованиях любят такие истории про реализацию алгоритмов своими руками.
«Прошу взять тот факт за внимания» это на каком языке?)
А все-таки, как этот проект помешал поступлению в ВУЗ?
Убитое время. Вместо проекта мог бы его потратить на подготовку к ЕГЭ

ЕГЭ не готовит к реальной жизни, он готовит только для поступления в вуз. Такие проекты — готовят.
То, что хочется пионерить и писать решения самому в ущерб «best practices» — это нормально и правильно в вашем возрасте.


Понятно, что «старичок» просто бы настроил Elasticsearch, взял пару готовых библиотек, написал бы обвязку за пару вечеров,
и писать было бы не о чем. У меня при прочтении тоже возникло много вопросов из серии «чем не угодил эластик?», «почему авторизация своя?» и т. п. Но потом я посмотрел на возраст автора и заплюсовал статью. Да, код неказистый, да, состоит из велосипедов, но каков запал, какая целеустремлённость! Вы даже не поленились потрясти Абби по поводу проприетарной библиотеки, а это много стоит, на самом деле.


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

НЛО прилетело и опубликовало эту надпись здесь
Это я опрометчиво такую фразу оставил :) Давайте не будем разжигать конфликт по этому поводу. Признаю свою вину в этом вопросе.
К тому же, в исходниках данного проекта я обнаружил пару грубых алгоритмических ошибок, исправление которых может затянуться на доооолго.

Issue открыли?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории