Упругий поиск в ASP.NET - с использованием знака амперсанда - PullRequest
0 голосов
/ 15 марта 2019

Я новичок в Elastic Search в ASP.NET, и у меня есть проблема, которую я до сих пор не могу решить.

Из документации я видел, что знак & не указан в качестве специального символа. Тем не менее, когда я отправляю свой поиск знак амперсанда полностью игнорируется. Например, если я ищу знак procter & gamble, знак & полностью игнорируется. Это создает для меня много проблем, потому что у меня есть такие компании, как M&S. Когда знак & игнорируется, я получаю в основном все, что содержит М или S. Если я пытаюсь с точным поиском (M&S), у меня та же проблема.

Мой код:

void Connect()
{            
    node = new Uri(ConfigurationManager.AppSettings["Url"]);
    settings = new ConnectionSettings(node);
    settings.DefaultIndex(ConfigurationManager.AppSettings["defaultIndex"]);
    settings.ThrowExceptions(true);
    client = new ElasticClient(settings);                        
}

private string escapeChars(string inStr) {
    var temp = inStr;
    temp = temp
        .Replace(@"\", @"\\")
        .Replace(@">",string.Empty)
        .Replace(@"<",string.Empty)
        .Replace(@"{",string.Empty)
        .Replace(@"}",string.Empty)
        .Replace(@"[",string.Empty)
        .Replace(@"]",string.Empty)
        .Replace(@"*",string.Empty)
        .Replace(@"?",string.Empty)
        .Replace(@":",string.Empty)
        .Replace(@"/",string.Empty);
    return temp;
}

А потом внутри одной из моих функций

Connect();    
ISearchResponse<ElasticSearch_Result> search_result;            
var QString = escapeChars(searchString);                  
search_result = client.Search<ElasticSearch_Result>(s => s
    .From(0)
    .Size(101)
    .Query(q => 
        q.QueryString(b => 
            b.Query(QString)
            //.Analyzer("whitespace")
            .Fields(fs => fs.Field(f => f.CompanyName))                                
        )
    )
    .Highlight(h => h
        .Order("score")
        .TagsSchema("styled")
        .Fields(fs => fs
            .Field(f => f.CompanyName)
        )
    )
);

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

Я бы хотел иметь следующий сценарий:

Поиск: M&S Company Foo Bar

Жетоны: M&S Company Foo Bar + бонус, если возможно иметь M S жетонов тоже

Я использую упругий поиск V5.0.

Любая помощь приветствуется. Включая лучшую документацию, чем та, которую можно найти здесь: https://www.elastic.co/guide/en/elasticsearch/client/net-api/5.x/writing-queries.html.

1 Ответ

2 голосов
/ 15 марта 2019

По умолчанию для текстового поля применяется анализатор стандартный анализатор .Этот анализатор применяет стандартный токенизатор вместе с строчным фильтром токенов .Поэтому, когда вы индексируете какое-то значение для этого поля, к этому значению применяется стандартный анализатор, а результирующие токены индексируются для этого поля.

Давайте разберемся в этом, например, для поля companyName (тип текста)давайте предположим, что переданное значение равно M&S Company Foo Bar при индексации документа.Результирующие токены для этого значения после применения стандартного анализатора будут:

m
s
company
foo
bar

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

Когда вы выполняете запрос к этому полю и не пропускаете анализатор в поисковом запросе, по умолчанию применяется тот же анализатор для поиска, который применяется для индексации по полю.Поэтому, если вы ищете M&S, он получает токены для M и S и, таким образом, выполняет поиск по этим двум токенам вместо M&S.

. Чтобы решить эту проблему, вам нужно изменитьанализатор для поля companyName.Вместо стандартного анализатора вы можете создать собственный анализатор, который использует токенайзер пробельных символов и фильтр нижнего регистра (чтобы сделать поиск регистронезависимым).Для этого вам нужно изменить настройку и отображение, как показано ниже:

{
  "settings": {
    "analysis": {
      "analyzer": {
        "whitespace_lowercase": {
          "tokenizer": "whitespace",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "companyName": {
          "type": "text",
          "analyzer": "whitespace_lowercase",
          "fields": {
            "keyword": {
              "type": "keyword"
            }
          }
        }
      }
    }
  }
}

Теперь для вышеприведенного ввода сгенерированные токены будут:

m&s
company
foo
bar

Это будет гарантировать, что при поиске M&S, & не игнорируется.

...