如何构建弹性搜索查询,以使文档字段中的每个标记都匹配?

时间:2013-01-31 15:20:44

标签: elasticsearch

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

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

Store_Name = "Square Steakhouse"

当用户搜索Square或Steakhouse时,构建与该文档匹配的查询很简单。此外,将kstem过滤器连接到默认分析仪,牛排餐厅也可能匹配。

{
  "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,小写过滤器以及标准标记器

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

这在弹性搜索中是否可行?

1 个答案:

答案 0 :(得分:4)

这是一个很好的方法。

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

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

您需要使用analyze 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]
        }
      }
    }
  }
}
  • 将[查询]替换为搜索字词
  • 将[tokencount]替换为搜索字词中的令牌数量(使用上面的GetTokenCount函数

这可确保所有匹配项都至少与MyField中的令牌匹配。

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

<强>参考