【问题标题】:how to make contains/ like query with elasticsearch?如何使用elasticsearch进行包含/喜欢查询?
【发布时间】:2019-03-27 20:12:48
【问题描述】:

我想用 elelasticsearch 实现下面的 tsql 查询

declare @searchstring nvarchar (max) 

set @searchstring = 'tn-241'

set @searchstring = replace(replace('%'+@searchstring+'%', '-', ''), ' ', '')

    SELECT *
    FROM [dbo].[Product] 
    where 
        replace(replace(shortdescription, '-', ''), ' ', '') like @searchstring or
        replace(replace(name, '-', ''), ' ', '') like @searchstring or
        replace(replace(number, '-', ''), ' ', '') like  @searchstring

为此,我使用关键字标记器和分隔符过滤器和 catenate_all 创建了分析器,如下所示

"search_delimiter": {
"split_on_numerics": "false",
"generate_word_parts": "false",
"preserve_original": "false",
"generate_number_parts": "false",
"catenate_all": "true",
"split_on_case_change": "false",
"type": "word_delimiter",
"stem_english_possessive": "false"
}
       "analyzer": {
    "searchanalyzer": {
    "filter": [
    "lowercase"
    ,
    "search_delimiter"
    ],
    "type": "custom",
    "tokenizer": "keyword"


},
"Name": {
"analyzer": "searchanalyzer",
"type": "string",
"fields": {
"raw": {
"analyzer": "searchanalyzer",
"type": "string"
}
}
},
"Number": {
"analyzer": "searchanalyzer",
"type": "string",
"fields": {
"raw": {
"analyzer": "searchanalyzer",
"type": "string"
}
}
}
"ShortDescription": {
"analyzer": "searchanalyzer",
"type": "string",
"fields": {
"raw": {
"analyzer": "searchanalyzer",
"type": "string"
}
}
},

结果为

curl -XGET "Index/_analyze?analyzer=searchanalyzer&pretty=true" -d "Original Brother TN-241C Toner Cyan"
{
  "tokens" : [ {
    "token" : "originalbrothertn241ctonercyan",
    "start_offset" : 0,
    "end_offset" : 35,
    "type" : "word",
    "position" : 0
  } ]
}
}

所以我需要基本上应用相同的分析器并使用应该进行字符串搜索的 query_string 或通配符搜索

所以如果我像下面这样搜索

"query": {
    "query_string" : {
        "fields" : ["Name", "Number", "ShortDescription"],
        "query" : "*TonerCyan*"           
    }
}

它工作正常,但如果我搜索

  "query": {
        "query_string" : {
            "fields" : ["Name", "Number", "ShortDescription"],
            "query" : "*Toner Cyan*"           
        }
    }

它不会返回任何结果,这意味着在执行 query_string 之前未应用 searchanalyzer,因为我希望它应该在第二个查询中搜索 TonerCyan,而不是分别搜索 Toner 和 Cyan?第一个问题是为什么这不起作用?第二个是实现上述 tsql 查询的最佳方法是什么?它应该搜索多个字段

【问题讨论】:

  • 这个答案可能会有所帮助:stackoverflow.com/questions/30666371/…
  • @Val 感谢您的回答,但我已经有使用 nedgegram 分析器的经验,虽然它是最好的分析器之一,但它不适合我们的情况,它基本上返回的结果比预期的要多得多。当有 -, /,( 等标志时,它在很多情况下都会失败。我肯定将它与标准、关键字和空白分析器结合使用,但无法达到预期的结果。我相信上面的分析器非常适合我们的案例,它做了应该做的事情用于索引,但我不明白为什么它不适用于搜索分析器
  • @Val 我不得不承认,我不擅长 query_string,所以我不知道它的原理,但是当我使用多匹配或匹配查询时,搜索分析器按预期工作,但多匹配查询不像 query_string 那样提供包含查询。或者也许可以用通配符来实现,但我就是想不通
  • @Val 你的例子和我们的一样,但我需要更多像 table1, table-1, table/1,table 1 应该有完全相同的结果。这就是为什么我刚刚在上面创建了 searchanalyzer,它删除了所有特殊字符和空格,并使其仅用于搜索时间的“table1”,它也应该做索引值和 table1 query_string 应该匹配。但很明显,在搜索时,searcanalyzer 并没有申请搜索关键字

标签: elasticsearch


【解决方案1】:

您可以尝试将搜索字符串放在这样的双引号内,这样应该可以:

{
  "query": {
    "query_string": {
      "fields": [
        "Name",
        "Number",
        "ShortDescription"
      ],
      "query": "*\"Toner Cyan\"*"
    }
  }
}

此外,您应该知道搜索前缀通配符可能会对性能产生灾难性影响,具体取决于您拥有的数据量。出于这个原因,我仍然坚信您应该为 ngram 编制索引。

【讨论】:

  • 双引号确实有效,但这是什么意思?双引号在这里做什么?
  • 双引号防止输入被标记为两个标记
  • 这个肯定有效。这就是为什么我竖起大拇指,但我仍在评估性能和更好的选择。否则我会接受你的回复。再次感谢
  • 我已经暗示了在我早期的 cmets 和我的回答结束时会有什么更好的选择:使用 ngrams ;-)
猜你喜欢
  • 2011-08-02
  • 2015-04-03
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 2019-04-17
  • 2014-03-30
  • 1970-01-01
  • 2012-12-23
相关资源
最近更新 更多