impwx
@impwx
Разработчик

Как реализовать поиск по фамилиям в базе?

Допустим, есть таблица с двумя полями: id и data. В поле data хранится произвольный текст на русском языке, в котором могут быть имена и фамилии. Нужно реализовать поиск по этой таблице:

Требования к поиску:
  • Независимость от падежа ("иванова" совпадает с "иванов", "ивановых", "ивановичев")
  • Толерантность к опечаткам ("сименов" совпадает с "семёнов")
  • Ранжирование по релевантности

Попробовал полнотекстовый поиск PostgreSQL с пакетом pg_tgrm, как надо не работает:

SELECT to_tsvector('russian', 'Анна Иванова') @@ to_tsquery('russian', 'иванов') -- false
SELECT to_tsvector('russian', 'Иван Иванов') @@ to_tsquery('russian', 'иванова') -- false

SELECT similarity('иванов', 'иванова') -- 0.66
SELECT similarity('иванов', 'ивановым') -- 0.6
SELECT similarity('иваныч', 'иванович') -- 0.33

Аналогично, ElasticSearch тоже ничего не находит:

client.CreateIndex(
	index,
	m => m.Mappings(mp =>
		mp.Map<Page>(mx =>
			mx.Properties(p =>
				p.Text(x =>
					x.Name(f => f.Title)
					.Analyzer("index_ru")
					.SearchAnalyzer("search_ru")
				)
			)
		)
	)
	.Settings(s =>
		s.Analysis(a => 
			a.CharFilters(c =>
				c.Mapping("filter_ru_e", z => z.Mappings("Ё => Е", "ё => е"))
			)
			.Tokenizers(t =>
				t.NGram("n_gram", ng =>
					ng.MinGram(4).MaxGram(20)
				)
			)
			.Analyzers(an => 
				an.Custom("index_ru", ac =>
					ac.CharFilters("html_strip", "filter_ru_e")
					.Tokenizer("n_gram")
					.Filters("stop", "lowercase", "russian_morphology", "english_morphology")
				)
				.Custom("search_ru", ac =>
					ac.CharFilters("html_strip", "filter_ru_e")
					.Tokenizer("standard")
					.Filters("stop", "lowercase", "russian_morphology", "english_morphology")
				)
			)
		)
	)
);

var docs = new []
{
	new Page("Иван Иванов"),
	new Page("Петр Иванов"),
	new Page("Илья Иванов"),
	new Page("Светлана Иванова"),
	new Page("Анна Иванова"),
};

foreach(var doc in docs)
	client.Index(doc);
	
var query = client.Search<Page>(
	s => s.Query(
		q => q.Match(
			f => f.Field(x => x.Title)
				  .Query("иванов")
		)
	)
);

Неужели нет готового инструмента, который работает как следует?
  • Вопрос задан
  • 132 просмотра
Пригласить эксперта
Ответы на вопрос 2
  • mindtester
    @mindtester
    а как вы думаете? почему все еще не вышла кортана на русском?

    ps

    это не об уникальности русского языка, просто тема еще не перешла в разряд тривиальных, на данном этапе развития ИТ

    посмотрите услуги и наработки сервиса https://dadata.ru/ вдруг что то пригодится
    Ответ написан
  • leahch
    @leahch
    Я мастер на все руки, я козлик Элек Мэк :-)
    Странно, у меня для русских полей стоит russian аналайзер, из коробки, ищет по словоформам неплохо, но на фамилиях не тестировал. Попробуйте еще и fuzzy query.
    Вот прямо сейчас проверил: "лебедь датчик", находит "Светильник Лебеди ночник с датчиком света Космос".
    Ищу площадки, получаю "Серая площадка и круглая черн.ручка под замок"
    Ищу лампа, находит и лампу и лампой и лампы, и лампа.
    Ищу гвоздь, получаю Скоба пластиковая с гвоздем
    PS. Elasticsearch 5.1.1 если чо. Специально никаких плагинов с русской морфологией не ставлю с версии 2.x
    Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы