【问题标题】:How do I build an elastic search query such that each token in a document field is matched?如何构建弹性搜索查询以匹配文档字段中的每个标记?
【发布时间】:2013-01-15 18:03:21
【问题描述】:

我需要确保字段的每个标记都与用户搜索中的至少一个标记匹配。

为简化起见,这是一个通用示例。

Store_Name = "Square Steakhouse"

当用户搜索 Square 或 Steakhouse 时,构建与此文档匹配的查询很简单。此外,通过将 kstem 过滤器附加到默认分析器,Steakhouses 也可能匹配。

{
  "size": 30,
  "query": {
    "match": {
      "Store_Name": {
        "query": "Square",
        "operator": "AND"
      }
    }
  }
}

不幸的是,我需要匹配 Store_Name 字段的每个标记。我需要以下行为:

Query: Square Steakhouse    Result: Match
Query: Square Steakhouses   Result: Match
Query: Squared Steakhouse   Result: Match
Query: Square               Result: No Match
Query: Steakhouse           Result: No Match

总结

  • 不能使用 not_analyzed,因为我确实需要利用分析器功能
  • 我打算使用 kstem、自定义同义词、自定义 char_filter、小写过滤器以及标准标记器

但是,我需要确保字段的每个标记都匹配

这在弹性搜索中可行吗?

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    这是一个好方法。

    它并不完美,但在简单性、计算和存储方面是一个很好的折衷方案。

    • 索引字段的标记计数
    • 获取搜索文本的token计数
    • 执行过滤查询并强制结果之间的令牌数相等

    您将需要使用分析 API 来获取令牌计数。确保使用与相关字段相同的分析器。这是一个获取令牌计数的 VB.NET 函数:

    Private Function GetTokenCount(ByVal RawString As String, Optional ByVal Analyzer As String = "default") As Integer
        If Trim(RawString) = "" Then Return 0
    
        Dim client = New ElasticConnection()
        Dim result = client.Post("http://localhost:9200/myindex/_analyze?analyzer=" & Analyzer, RawString) 'Submit analyze request usign PlainElastic.NET API
        Dim J = JObject.Parse(result.ToString()) 'Populate JSON.NET JObject
        Return (From X In J("tokens")).Count() 'returns token count using a JSON.NET JObject
    
    End Function
    

    您将希望在索引时使用它来存储相关字段的令牌计数。确保 TokenCount 的映射中有一个条目

    这是一个很好的弹性搜索查询,用于利用这个新的令牌计数信息:

    {
      "size": 30,
      "query": {
        "filtered": {
          "query": {
            "match": {
              "MyField": {
                "query": "[query]",
                "operator": "AND"
              }
            }
          },
          "filter": {
            "term": {
              "TokenCount": [tokencount]
            }
          }
        }
      }
    }
    
    • 将 [query] 替换为搜索词
    • 将 [tokencount] 替换为搜索词中的令牌数(使用上面的 GetTokenCount 函数

    这确保所有匹配项至少与MyField 中的标记一样多。

    以上有一些缺点。例如,如果我们正在匹配字段“blue red”,并且用户搜索“blue blue”,则上述将触发匹配。因此,您可能想要使用unique token filter。您可能还希望调整过滤器,以便

    参考

    【讨论】:

      猜你喜欢
      • 2020-11-10
      • 1970-01-01
      • 2016-01-01
      • 1970-01-01
      • 2020-11-09
      • 2021-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多