[Elasticsearch] 多字段搜索 (一) - 多个及单个查询字符串

多字段搜索(Multifield Search)

本文翻译自官方指南的Multifield Search一章。

查询很少是只拥有一个match查询子句的查询。我们经常需要对一个或者多个字段使用相同或者不同的查询字符串进行搜索,这意味着我们需要将多个查询子句和它们得到的相关度分值以一种有意义的方式进行合并。

也许我们正在寻找一本名为战争与和平的书,它的作者是Leo Tolstoy。也许我们正在使用"最少应该匹配(Minimum Should Match)"来搜索ES中的文档。另外我们也可能会寻找拥有名为John而姓为Smith的用户。

在本章中我们会讨论一些构建多字段搜索的工具,以及如何根据你的实际情况来决定使用哪种方案。


多个查询字符串(Multiple Query Strings)

处理字段查询最简单的方法是将搜索词条对应到特定的字段上。如果我们知道战争与和平是标题,而Leo Tolstoy是作者,那么我们可以简单地将每个条件当做一个match子句,然后通过bool查询将它们合并:

GET /_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title":  "War and Peace" }},
        { "match": { "author": "Leo Tolstoy"   }}
      ]
    }
  }
}

bool查询采用了一种"匹配越多越好(More-matches-is-better)"的方法,因此每个match子句的分值会被累加来得到文档最终的_score。匹配两个子句的文档相比那些只匹配一个子句的文档的分值会高一些。

当然,你并不是只能使用match子句:bool查询可以包含任何其他类型的查询,包括其它的bool查询。我们可以添加一个子句来指定我们希望的译者:

GET /_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title":  "War and Peace" }},
        { "match": { "author": "Leo Tolstoy"   }},
        { "bool":  {
          "should": [
            { "match": { "translator": "Constance Garnett" }},
            { "match": { "translator": "Louise Maude"      }}
          ]
        }}
      ]
    }
  }
}

我们为什么将译者的查询子句放在一个单独的bool查询中?所有的4个match查询都是should子句,那么为何不将译者的查询子句和标题及作者的查询子句放在同一层次上呢?

答案在于分值是如何计算的。bool查询会运行每个match查询,将它们的分值相加,然后乘以匹配的查询子句的数量,最后除以所有查询子句的数量。相同层次的每个子句都拥有相同的权重。在上述查询中,bool查询中包含的译者查询子句只占了总分值的三分之一。如果我们将译者查询子句放到和标题及作者相同的层次上,就会减少标题和作者子句的权重,让它们各自只占四分之一。

设置子句优先级

上述查询中每个子句占有三分之一的权重也许并不是我们需要的。相比译者字段,我们可能对标题和作者字段更有兴趣。我们对查询进行调整来让标题和作者相对更重要。

在所有可用措施中,我们可以采用的最简单的方法是boost参数。为了增加titleauthor字段的权重,我们可以给它们一个大于1boost值:

GET /_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { 
            "title":  {
              "query": "War and Peace",
              "boost": 2
        }}},
        { "match": { 
            "author":  {
              "query": "Leo Tolstoy",
              "boost": 2
        }}},
        { "bool":  { 
            "should": [
              { "match": { "translator": "Constance Garnett" }},
              { "match": { "translator": "Louise Maude"      }}
            ]
        }}
      ]
    }
  }
}

以上的title和k字段的boost值为2。 嵌套的bool查询自居的默认boost值为k。

通过试错(Trial and Error)的方式可以确定"最佳"的boost值:设置一个boost值,执行测试查询,重复这个过程。一个合理boost值的范围在110之间,也可能是15。比它更高的值的影响不会起到很大的作用,因为分值会被规范化(Normalized)


单一查询字符串(Single Query String)

bool查询是多字段查询的中流砥柱。在很多场合下它都能很好地工作,特别是当你能够将不同的查询字符串映射到不同的字段时。

问题在于,现在的用户期望能够在一个地方输入所有的搜索词条,然后应用能够知道如何为他们得到正确的结果。所以当我们把含有多个字段的搜索表单称为高级搜索(Advanced Search)时,是有一些讽刺意味的。高级搜索虽然对用户而言会显得更"高级",但是实际上它的实现方式更简单。

对于多词,多字段查询并没有一种万能的方法。要得到最佳的结果,你需要了解你的数据以及如何使用恰当的工具。

了解你的数据

当用户的唯一输入就是一个查询字符串时,你会经常碰到以下三种情况:

最佳字段(Best fields)

当搜索代表某些概念的单词时,例如"brown fox",几个单词合在一起表达出来的意思比单独的单词更多。类似title和body的字段,尽管它们是相关联的,但是也是互相竞争着的。文档在相同的字段中应该有尽可能多的单词(译注:搜索的目标单词),文档的分数应该来自拥有最佳匹配的字段。

多数字段(Most fields)

一个用来调优相关度的常用技术是将相同的数据索引到多个字段中,每个字段拥有自己的分析链(Analysis Chain)。

主要字段会含有单词的词干部分,同义词和消除了变音符号的单词。它用来尽可能多地匹配文档。

相同的文本可以被索引到其它的字段中来提供更加精确的匹配。一个字段或许会包含未被提取词干的单词,另一个字段是包含了变音符号的单词,第三个字段则使用shingle来提供关于单词邻近度(Word Proximity)的信息。

以上这些额外的字段扮演者signal的角色,用来增加每个匹配的文档的相关度分值。越多的字段被匹配则意味着文档的相关度越高。

跨字段(Cross fields)

对于一些实体,标识信息会在多个字段中出现,每个字段中只含有一部分信息:

  • Person:first_name 和 last_name
  • Book:titleauthor 和 description
  • Address:streetcitycountry 和 postcode

此时,我们希望在任意字段中找到尽可能多的单词。我们需要在多个字段中进行查询,就好像这些字段是一个字段那样。


以上这些都是多词,多字段查询,但是每种都需要使用不同的策略。我们会在本章剩下的部分解释每种策略。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在ES(Elasticsearch)中,可以通过使用多个模糊查询来实现在Java中进行搜索。 首先,需要使用Java的Elasticsearch客户端连接到ES集群。然后,可以使用ES的多个模糊查询功能来执行搜索操作。 在ES中,可以使用Fuzzy Query(模糊查询)来进行基于相似度的搜索。该查询可以根据指定的编辑距离(可以理解为字符串之间的差异程度)来匹配相关的文档或字段。 在Java中,可以使用ES的Java API来构建Fuzzy Query。首先,需要创建一个FuzzyQueryBuilder对象,并设置模糊查询字段和关键词。然后,可以设置模糊查询的参数,例如编辑距离和前缀长度。 接下来,可以使用Java的ES客户端的搜索方法执行模糊查询。该方法将查询对象作为参数传入,并返回匹配的结果。 例如,假设我们想要在名为"products"的索引的"name"字段查询包含模糊关键词"java"的文档。我们可以使用以下代码来实现: ``` import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.FuzzyQueryBuilder; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.search.SearchHit; RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); FuzzyQueryBuilder fuzzyQuery = QueryBuilders.fuzzyQuery("name", "java") .fuzziness(Fuzziness.AUTO) .prefixLength(0); SearchRequest searchRequest = new SearchRequest("products"); searchRequest.source().query(fuzzyQuery); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); SearchHit[] searchHits = searchResponse.getHits().getHits(); for (SearchHit searchHit : searchHits) { Map<String, Object> sourceMap = searchHit.getSourceAsMap(); System.out.println(sourceMap); // 打印匹配结果 } client.close(); ``` 以上代码演示了如何使用ES的Java API进行多个模糊查询。首先,创建了一个FuzzyQueryBuilder对象来设置模糊查询字段和关键词。然后,创建了一个SearchRequest对象来指定要搜索的索引和查询条件。最后,通过调用Java的ES客户端的search方法执行搜索,并遍历匹配的结果进行处理。 总结起来,ES提供了多个模糊查询的功能,可以通过ES的Java API在Java中进行实现。使用FuzzyQueryBuilder可以构建模糊查询,并通过Java的ES客户端执行搜索操作。 ### 回答2: ES(Elasticsearch)是一个开源的分布式搜索和分析引擎,可以提供快速的全文搜索、实时数据分析以及多维度的数据聚合功能。Java是一种面向对象的编程语言,也是ES的官方支持的编程语言之一。 在ES中进行多个模糊查询,可以通过使用模糊查询语法和多个查询组合来实现。ES提供了多种查询方式,包括基于词项匹配的查询(match query)、基于短语匹配的查询(match_phrase query)、基于通配符的查询(wildcard query)等。 对于模糊查询,可以使用通配符查询来实现模糊匹配。通配符查询支持使用通配符(*)表示任意多个字符,以及问号(?)表示单个字符。例如,可以使用通配符查询查询包含特定字符序列的文档。 另外,在ES中还可以使用模糊查询对文本进行近似匹配。模糊查询在匹配时会考虑到文本之间的相似性,可以通过设置模糊度参数(fuzziness)来调整近似匹配的程度。 Java作为ES官方支持的编程语言之一,可以使用Java API来进行ES的多个模糊查询。通过使用Java API,可以编写Java代码来构建和执行多个模糊查询,并获得查询结果。 总之,ES是一个强大的搜索和分析引擎,通过使用多个模糊查询可以实现对文本进行模糊匹配和近似匹配。Java作为ES的官方支持的编程语言之一,可以使用Java API来进行ES的多个模糊查询。同时,ES提供了丰富的查询方式和语法,可以根据需求选择合适的查询方式来实现多个模糊查询。 ### 回答3: ES(Elasticsearch)是一个开源的分布式全文搜索和分析引擎,而Java是一种编程语言。多个模糊查询是指在ES中进行多个模糊搜索。 在ES中,可以使用模糊查询(fuzzy query)来匹配与搜索项相似但不完全相同的文档。模糊查询基于Levenshtein距离(编辑距离)的算法,可以在给定最大编辑距离的情况下查找与搜索项相似的文档。 使用Java可以与ES进行交互,通过Java的API将模糊查询操作发送到ES中。首先,需要在Java代码中引入ES相关的库和类。然后,可以连接到ES集群,创建一个ES客户端对象。 在Java中,可以使用QueryBuilder类来构建模糊查询。模糊查询的关键是设置一个匹配项和一个模糊度(fuzziness)参数。匹配项可以是一个具体的词语或者短语,模糊度参数表示搜索时允许的最大编辑距离。 例如,在Java中进行多个模糊查询,可以使用BoolQueryBuilder来构建复合查询。可以使用should()方法将多个模糊查询添加到查询条件中。每个模糊查询可以使用fuzzyQuery()方法来构建。 最后,通过Java的API将查询发送到ES集群,并获取返回的结果。返回的结果可以是与模糊查询匹配的文档列表,可以根据需要进行进一步的处理和分析。 总之,ES可以进行多个模糊查询,而Java作为一种编程语言可以与ES进行交互,并使用其API来构建和发送模糊查询。这样可以在ES中进行高效的模糊搜索,并获取匹配的文档结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值