ASP.NET中的弹性搜索-使用&符号

时间:2019-03-15 10:34:36

标签: asp.net asp.net-mvc elasticsearch tokenize

我是ASP.NET中的Elastic Search的新手,到目前为止,我有一个问题无法解决。

从文档中,我已经看到&符号没有作为特殊字符列出。但是,当我提交搜索与符号时,它会被完全忽略。例如,如果我搜索procter & gamble,则&符号将被完全忽略。这给我带来了很多问题,因为我有一些公司的名字像M&S。当&符号被忽略时,我基本上得到了所有带有M或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 个答案:

答案 0 :(得分:2)

默认情况下,分析器应用的文本字段为standard analyzer。该分析器将standard tokenizerlowercase token filter一起使用。因此,当您根据该字段为某个值编制索引时,标准分析器将应用于该值,并且由此产生的令牌也将针对该字段编制索引。

让我们通过例如对于字段companyName(文本类型),我们假设索引文档时传递的值为M&S Company Foo Bar。应用标准分析仪后,该值的结果标记为:

m
s
company
foo
bar

您会注意到,不仅空格,而且&都被用作分隔符,用于分割和生成令牌。

当您对此字段进行查询并且未在搜索查询中传递任何分析器时,默认情况下,它也会应用同一分析器进行搜索,该分析器也将用于对该字段建立索引。因此,如果您搜索M&S,它将被标记为MS,因此实际的搜索查询将搜索这两个标记而不是M&S

要解决此问题,您需要更改字段companyName的分析器。可以使用whitespace tokenizer和小写过滤器来创建自定义分析器,而不是标准分析器(以使搜索不区分大小写)。为此,您需要如下更改设置和映射:

{
  "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时不会忽略&