Elasticsearch学习笔记-多字段搜索

168 阅读2分钟

1、多词查询

#match 查询可以接受 operator 操作符作为输入参数,默认情况下该操作符是 or 。
$ curl -XGET 'http://localhost:9200/trade/share/_search' -d '
{
    "query": {
        "match": {
            "title": {      
                "query": "BROWN DOG!", #同时包含BROWN和DOG的文档才会搜索到
                "operator": "and"
            }
        }
    }
}'

#match 查询支持 minimum_should_match 最小匹配参数,指定必须匹配的词项数用来表示一个文档是否相关。
$ curl -XGET 'http://localhost:9200/trade/share/_search' -d '
{
  "query": {
    "match": {
      "title": {
        "query": "quick brown dog",
        "minimum_should_match": "75%"
      }
    }
  }
}'
注:75%会自动被截断成66.6%,即三个里面两个词。无论这个值设置成什么,至少包含一个词项的文档才会被认为是匹配的。

2、组合查询

bool 查询会为每个文档计算相关度评分 _score ,再将所有匹配的 must 和 should 语句的分数 _score 求和,最后除以 must 和 should 语句的总数。
must_not 语句不会影响评分,它的作用只是将不相关的文档排除。

所有 must 语句必须匹配,所有 must_not 语句都必须不匹配,默认情况下,没有 should 语句是必须匹配的,只有一个例外:那就是当没有 must 语句的时候,至少有一个 should 语句必须匹配。

可以通过 minimum_should_match 参数控制需要匹配的 should 语句的数量,它既可以是一个绝对的数字,又可以是个百分比
$ curl -XGET 'http://localhost:9200/trade/share/_search' -d '
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title": "brown" }},
        { "match": { "title": "fox" }},
        { "match": { "title": "dog" }}
      ],
      "minimum_should_match": 2 
    }
  }
}’

3、提升查询语句权重

可以通过指定 boost 来控制任何查询语句的相对的权重, boost 的默认值为 1 ,大于 1 会提升一个语句的相对权重。
$ curl -XGET 'http://localhost:9200/trade/share/_search' -d '
{
    "query": {
        "bool": {
            "must": {
                "match": { #使用默认的 boost 值 1 
                    "content": { #content 字段必须包含 full 、 text 和 search 所有三个词。
                        "query": "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [
                { "match": {
                    "content": {
                        "query": "Elasticsearch",
                        "boost": 3
                    }
                }},
                { "match": {
                    "content": {
                        "query": "Lucene",
                        "boost": 2 
                    }
                }}
            ]
        }
    }
}'

4、multi_match查询

#multi_match 能在多个字段上反复执行相同查询。
{
    "multi_match": {
        "query": "Quick brown fox",
        "type": "best_fields",  #默认类型,可以不指定
        "fields": [ "title", "body" ],
        "tie_breaker": 0.3,
        "minimum_should_match": "30%" 
    }
}

#查询字段名称的模糊匹配
{
    "multi_match": {
        "query":  "Quick brown fox",
        "fields": "*_title" #可同时匹配 book_title 、 chapter_title 和 section_title等格式字段值
    }
}

#提升单个字段的权重
{
    "multi_match": {
        "query":  "Quick brown fox",
        "fields": [ "*_title", "chapter_title^2" ]  #chapter_title 这个字段的 boost 值为 2,其它默认 boost 值为 1 
    }
}

5、最佳字段(best_fields)

#示例文档1:
$ PUT /trade/share/1
{
    "title": "Quick brown rabbits",
    "body":  "Brown rabbits are commonly seen."
}
#示例文档2:
$ PUT /trade/share/2
{
    "title": "Keeping pets healthy",
    "body":  "My quick brown fox eats rabbits on a regular basis."
}

#执行查询
$ GET /trade/share/_search
{
    "query": {
        "bool": {
            "should": [
                { "match": { "title": "Brown fox" }},
                { "match": { "body":  "Brown fox" }}
            ]
        }
    }
}
结果:文档 1 的评分更高
#分析:
bool 计算评分过程
1> 会执行 should 语句中的两个查询。
2> 加和两个查询的评分。
3> 乘以匹配语句的总数。
4> 除以所有语句总数(这里为2)。
文档 1 的两个字段都包含 brown 这个词,所以两个 match 语句都能成功匹配并且有一个评分。文档 2 的 body 字段同时包含 brown 和 fox 这两个词,但 title 字段没有包含任何词。这样, body 查询结果中的高分,加上 title 查询中的 0 分,然后乘以二分之一,就得到比文档 1 更低的整体评分。

#使用dis_max查询可以将任何与任一查询匹配的文档作为结果返回,但只将最佳匹配的评分作为查询的评分结果返回
{
    "query": {
        "dis_max": {
            "queries": [
                { "match": { "title": "Brown fox" }},
                { "match": { "body":  "Brown fox" }}
            ]
        }
    }
}
结果:文档 2 的评分更高

6、 最佳字段查询优化

当搜索 “quick pets” 时,在前面的两个文档都包含词 quick ,但是只有文档 2 包含词 pets ,两个文档中都不具有同时包含两个词的相同字段 ,此时两个文档的评分相同。

#使用tie_breaker可以将其他匹配语句的评分也考虑其中
{
    "query": {
        "dis_max": {
            "queries": [
                { "match": { "title": "Quick pets" }},
                { "match": { "body":  "Quick pets" }}
            ],
            "tie_breaker": 0.3
        }
    }
}
结果:文档 2 的相关度比文档 1 高
#tie_breaker 可以是 0 到 1 之间的浮点数,其中 0 代表使用 dis_max 最佳匹配语句的普通逻辑, 1 表示所有匹配语句同等重要。最佳的精确值需要根据数据与查询调试得出,合理值应该与零接近(处于 0.1 - 0.4 之间),这样就不会颠覆 dis_max 最佳匹配性质的根本。

7、多数字段(most_fields)

$ PUT /trade
{
    "settings": { "number_of_shards": 1 }, 
    "mappings": {
        "share": {
            "properties": {
                "title": { 
                    "type":     "string",
                    "analyzer": "english", #title 字段使用 english 英语分析器来提取词干
                    "fields": {
                        "std":   { 
                            "type":     "string",
                            "analyzer": "standard" #title.std 字段使用 standard 标准分析器,所以没有词干提取
                        }
                    }
                }
            }
        }
    }
}
#索引以下文档
$ PUT /trade/share/1
{ "title": "My rabbit jumps" }

$ PUT /trade/share/2
{ "title": "Jumping jack rabbits" }

#使用 match 查询 title 标题字段是否包含 jumping rabbits
$ GET /trade/_search
{
   "query": {
        "match": {
            "title": "jumping rabbits"
        }
    }
}
结果:因为使用 english 分析器,查询是在查找以 jump 和 rabbit 这两个被提取词的文档。两个文档的 title 字段都同时包括这两个词,所以两个文档得到的评分也相同。如果只是查询 title.std 字段,那么只有文档 2 是匹配的。
$ GET /my_index/_search
{
   "query": {
        "multi_match": {
            "query":  "jumping rabbits",
            "type":   "most_fields", 
            "fields": [ "title", "title.std" ]
        }
    }
}

#每个字段对于最终评分的贡献可以通过自定义值 boost 来控制。比如,使 title 字段更为重要,这样同时也降低了其他信号字段的作用
$ GET /my_index/_search
{
   "query": {
        "multi_match": {
            "query":       "jumping rabbits",
            "type":        "most_fields",
            "fields":      [ "title^10", "title.std" ] #title 字段的 boost 的值为 10 使它比 title.std 更重要
        }
    }
}