如何在可搜索字段中的单词内搜索? “包含”搜索

时间:2017-05-30 18:23:22

标签: azure-search

我有一个包含4个自定义分析器的搜索索引。其中两个用于特定语言搜索,另外两个用于“精确”搜索(不需要词形化)。为简单起见,我仅包含特定于语言的自定义分析仪的信息,但整体解决方案需要适用于所有自定义分析仪。

"tokenizers": [
{
"@odata.type": "#Microsoft.Azure.Search.MicrosoftLanguageStemmingTokenizer",
"name": "text_language_search_custom_analyzer_ms_tokenizer",
"maxTokenLength": 300,
"isSearchTokenizer": false,
"language": "french"
},
{
"@odata.type": "#Microsoft.Azure.Search.MicrosoftLanguageStemmingTokenizer",
"name": "text_language_search_endsWith_custom_analyzer_ms_tokenizer",
"maxTokenLength": 300,
"isSearchTokenizer": false,
"language": "french"
}
],
"analyzers": [
{
"@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
"name": "text_language_search_custom_analyzer",
"tokenizer": "text_language_search_custom_analyzer_ms_tokenizer",
"tokenFilters": [
"lowercase",
"lang_text_synonym_token_filter",
"asciifolding"
],
"charFilters": [ "html_strip" ]
},
{
"@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
"name": "text_language_search_endsWith_custom_analyzer",
"tokenizer": "text_language_search_endsWith_custom_analyzer_ms_tokenizer",
"tokenFilters": [
"lowercase",
"lang_text_endsWith_synonym_token_filter",
"asciifolding",
"reverse"
],
"charFilters": [ "html_strip" ]
}, ....

为简单起见,我们假设索引只有2个可搜索字段。   - CategoryLangSearch(使用text_language_search_custom_analyzer)   - CategoryLangSearchEndsWith(使用text_language_search_endsWith_custom_analyzer)

现在假设索引只有1个文档,具有以下内容:   - CategoryLangSearch“TELECOMMUNICATIONS”的字段值   - CategoryLangSearchEndsWith“TELECOMMUNICATIONS”的字段值

我们的UI / API层具有逻辑,因此如果用户搜索TELE *,它现在将使用CategoryLangSearch作为要搜索的字段。同样,我们的UI / API层将检测用户是否在星号中使用星号通配符进行搜索。面前。因此,如果用户搜索* TIONS,则UI / API层足够智能,而不是搜索CategoryLangSearchEndsWith字段。

一切都很棒......它完全符合预期。

但问题是,如果用户使用* COMMU *进行搜索,我们可以做些什么 (忽略空格...... S.O.将星号视为粗体信号。用户输入asteriskCOMMUasterisk,其中星号为*)

如果我像这样构建azure搜索参数,我认为这将是“聪明的”:(CategoryLangSearch:(COMMU *)OR CategoryLangSearchEndsWith:(* UMMOC))但是,在实践中,我发现这没有找到电信组织。当我看到我们构建的查询时,这非常有意义。

所以,我的问题是,我们如何解决这个问题呢?我们可以在Azure Search中以任何方式,形状或形式将其删除吗?我没有看到这个成功之路。我能看到的唯一可行解决方案如下:  1.如果用户搜索某事 ...  2.首先直接查询我们的MS SQL服务器,使用SQL支持的%something%语法进行搜索。  3.找到匹配的ID,然后使用THAT搜索Azure搜索索引。

2 个答案:

答案 0 :(得分:1)

有两种方法可以在Azure搜索中发出“包含”搜索。

  1. 第一种方法是在Lucene查询语法中使用regex表达式。在您的示例中,如果您发出正则表达式查询/.*COMMU.*/,搜索查询将首先扩展到搜索索引中包含字符串'commu'的所有项,然后查找结果。您可以针对“完全”匹配对字段发出正则表达式查询。搜索查询看起来像: ?文档搜索= exact_field:/.* COMMU * /&放大器;查询类型=满。

  2. 如果索引较小,建议使用上述方法,因为查找查询模式的查询扩展过程代价很高,尤其是对于/.*a.*/等广泛搜索。您可以在索引时使用ngram tokenfilter预加载工作。 tokenfilter的配置如下。

  3. {
      "@odata.type": "#Microsoft.Azure.Search.NGramTokenFilterV2",
      "name": "ngram_tokenfilter",
      "minGram": 1,
      "maxGram": 100
    }
    

    例如,给定一个文本“hello”,这个tokenfilter生成ngram标记为

      

    h,e,l,l,o,he,el,ll,lo,hel,ell,...,你好。

    查询使用ngram tokenfilter分析的新字段时,您不需要使用通配符或正则表达式运算符,但可以使用常规术语搜索。搜索查询“docs?search = ell”将找到包含术语“hello”的文档。这种方法避免了昂贵的扩展过程,因为所有“包含”的可能性都已经过预处理,并且存在于索引中。请注意,您只需要在索引时进行ngram分析。

    请注意,此ngram分析会影响索引的大小,因为它会生成更多令牌。您可以使用参数'minGram'和'maxGram'来控制索引的大小。

    由于您已经有一个基于'*'位置指向搜索的API / UI,第二个选项似乎是一个很好的方法。

    内特

答案 1 :(得分:0)

很棒的答案Nate! 但这不完全正确。

如果您像这样使用“ngram_tokenfilter”,它将生成正好六个令牌: {h,他,嗨,地狱,你好} 。 您可以创建第二个“ngram_tokenfilter”并将“side”参数设置为“back”以获得所需的行为。

我有一个非常类似的问题,也许它可以提供帮助:Azure-search: How to get documents which exectly contain search term

祝你们玩得愉快!