[Elasticsearch]多字段搜索(⼀)-多个及单个查询字符串
多字段搜索(Multifield Search)
本⽂翻译⾃官⽅指南的⼀章。
查询很少是只拥有⼀个match查询⼦句的查询。我们经常需要对⼀个或者多个字段使⽤相同或者不同的查询字符串进⾏搜索,这意味着我们需要将多个查询⼦句和它们得到的相关度分值以⼀种有意义的⽅式进⾏合并。
也许我们正在寻⼀本名为战争与和平的书,它的作者是Leo Tolstoy。也许我们正在使⽤"最少应该匹配(Minimum Should Match)"来搜索ES中的⽂档。另外我们也可能会寻拥有名为John⽽姓为Smith的⽤户。
在本章中我们会讨论⼀些构建多字段搜索的⼯具,以及如何根据你的实际情况来决定使⽤哪种⽅案。
多个查询字符串(Multiple Query Strings)
处理字段查询最简单的⽅法是将搜索词条对应到特定的字段上。如果我们知道战争与和平是标题,⽽Leo Tolstoy是作者,那么我们可以简单地将每个条件当做⼀个match⼦句,然后通过将它们合并:
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参数。为了增加title和author字段的权重,我们可以给它们⼀个⼤于1的boost值:
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值的范围单个字符视为长度为1的字符串
在1和10之间,也可能是15。⽐它更⾼的值的影响不会起到很⼤的作⽤,因为分值会被。
单⼀查询字符串(Single Query String)
bool查询是多字段查询的中流砥柱。在很多场合下它都能很好地⼯作,特别是当你能够将不同的查询字符串映射到不同的字段时。
问题在于,现在的⽤户期望能够在⼀个地⽅输⼊所有的搜索词条,然后应⽤能够知道如何为他们得到正确的结果。所以当我们把含有多个字段的搜索表单称为⾼级搜索(Advanced Search)时,是有⼀些讽刺意味的。⾼级搜索虽然对⽤户⽽⾔会显得更"⾼级",但是实际上它的实现⽅式更简单。
对于多词,多字段查询并没有⼀种万能的⽅法。要得到最佳的结果,你需要了解你的数据以及如何使⽤恰当的⼯具。
了解你的数据
当⽤户的唯⼀输⼊就是⼀个查询字符串时,你会经常碰到以下三种情况:
最佳字段(Best fields)
当搜索代表某些概念的单词时,例如"brown fox",⼏个单词合在⼀起表达出来的意思⽐单独的单词更多。类似title和body的字段,尽管它们是相关联的,但是也是互相竞争着的。⽂档在相同的字段中应该有尽可能多的单词(译注:搜索的⽬标单词),⽂档的分数应该来⾃拥有最佳匹配的字段。
多数字段(Most fields)
⼀个⽤来调优相关度的常⽤技术是将相同的数据索引到多个字段中,每个字段拥有⾃⼰的分析链(Analysis Chain)。
主要字段会含有单词的词⼲部分,同义词和消除了变⾳符号的单词。它⽤来尽可能多地匹配⽂档。
相同的⽂本可以被索引到其它的字段中来提供更加精确的匹配。⼀个字段或许会包含未被提取词⼲的单词,另⼀个字段是包含了变⾳符号的单词,第三个字段则使⽤shingle来提供关于的信息。
以上这些额外的字段扮演者signal的⾓⾊,⽤来增加每个匹配的⽂档的相关度分值。越多的字段被匹配则意味着⽂档的相关度越⾼。
跨字段(Cross fields)
对于⼀些实体,标识信息会在多个字段中出现,每个字段中只含有⼀部分信息:
Person:first_name和last_name
Book:title,author和description
Address:street,city,country和postcode
此时,我们希望在任意字段中到尽可能多的单词。我们需要在多个字段中进⾏查询,就好像这些字段是⼀个字段那样。以上这些都是多词,多字段查询,但是每种都需要使⽤不同的策略。我们会在本章剩下的部分解释每种策略。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。