Регистронезависимый поля в Elasticsearch
Я использую NEST с ElasticSearch, и я пытаюсь найти, позволяя пользователям вводить поисковые фразы в поле поиска. Все работает нормально, кроме того, когда пользователь вводит поисковую фразу, Им нужно убедиться, что имя поля совпадает с именем Поля в эластичном поиске.
например, одно из моих полей называется bookTitle. Если они ищут, как показано ниже, то это работает
bookTitle:"Сказка о двух городах"
если они ищут, как пример ниже не работает
booktitle: "Сказка о двух городах" BookTitle:"Сказка о двух городах"
код, который я использую для поиска, приведен ниже. У кого-нибудь есть идеи, как я могу это исправить. Я надеялся, что есть настройка ElasticSearch/NEST, которая позволяет мне делать это, а не делать что-то уродливое с текстом поиска, таким как поиск "BookTitle" и замена на "bookTitle".
public List<ElasticSearchRecord> Search(string searchterm) {
var results = _client.Search<ElasticSearchRecord>(s => s
.Query(q => q
.QueryString(qs => qs
.DefaultField("content")
.Query(searchterm)
)
));
return results.Documents.ToList();
}
любая помощь очень ценится.
3 ответов
то, как вы хотите, это невозможно с Elasticsearch. Вы контролируете отображение, вы определяете имена полей, вы тот, кто контролирует запросы.
по этому мнению, вам нужно следить за тем, что ваши пользователи будут вводить в поле поиска, Elasticsearch out-of-the-box не поможет вам с именами полей в нижнем регистре или что-то в этом роде.
Итак, какое бы решение вы ни выбрали, это будет обходной путь.
мой предложение определите набор правил, это также должно быть сообщено вашим пользователям. Что-то вокруг этих строк:
- ваши имена полей все строчные, или стиле Camel
- вы определяете отображение как
strict
Так что вы находитесь в полном контроле над ним - вы уведомляете пользователей (в веб-интерфейсе или пользовательском интерфейсе), что они должны искать имена полей с заданным набором правил (только в нижнем регистре или только в случае верблюда и т. д.)
другой подход заключается в определении что входит в _all
поле. И в вашем QueryString
вы не используете конкретные имена полей, и ES будет использовать query_string
по умолчанию. Это означает, что ES будет использовать _all
, an
вы можете кэшировать отображение в C# в памяти и подтвердить, что все поля поиска найдены из него. Если точное совпадение не найдено, попробуйте найти наиболее подходящие поля. Если есть несколько вариантов на выбор, то бросьте ошибку и попросите пользователя быть более конкретным.
на самом деле пользовательский интерфейс может сделать это на лету, как они печатают и помогают им выбрать правильный вариант.
еще не протестировали это как качество производства, но теоретически вы можете сохранить все свои объекты с помощью стратегии именования в нижнем регистре .ToLower () ваши запрашиваемые поля, чтобы они всегда совпадали.
Начнем с создания соответствующей стратегии именования:
public class LowercaseNamingStrategy : Newtonsoft.Json.Serialization.NamingStrategy
{
protected override string ResolvePropertyName(string name)
{
return name.ToLower();
}
}
и соответствующий сериализатор:
public class ElasticSerializer : JsonNetSerializer
{
public ElasticSerializer(IConnectionSettingsValues settings)
: base(settings)
{
this.ContractResolver.NamingStrategy = new LowercaseNamingStrategy();
}
}
затем используйте сериализатор в настройках подключения вашего клиента NEST:
var pool = new StaticConnectionPool([your nodes]);
var settings = new ConnectionSettings(pool, s => new ElasticSerializer(s));
var client = new ElasticClient(settings);
это сохранит ваши поля в нижнем регистре. Затем когда вы запрашиваете, просто заставьте все предоставленные пользователем поля быть строчными, и все должно выстраиваться.
Если вы не начинаете с нуля, вам придется заполнять свои данные, чтобы сохранить единую стратегию именования.