1、短语匹配
$ GET /trade/share/_search
{
"query": {
"match_phrase": {
"title": "quick brown fox"
}
}
}
match_phrase 查询首先将查询字符串解析成一个词项列表,然后对这些词项进行搜索,但只保留那些
包含 全部 搜索词项,且 位置 与搜索词项相同的文档。
#slop参数
例:包含 “quick brown fox” 的文档也能够匹配 “quick fox”。
$ GET /trade/share/_search
{
"query": {
"match_phrase": {
"title": {
"query": "quick fox",
"slop": 1
}
}
}
}
slop 参数告诉 match_phrase 查询词条相隔多远时仍然能将文档视为匹配 。
2、prefix前缀查询
$ GET /trade/address/_search
{
"query": {
"prefix": {
"postcode": "W1" #查找所有以 W1 开始的邮编
}
}
}
prefix 不会在搜索之前分析查询字符串,它假定传入前缀就正是要查找的前缀。
3、通配符与正则表达式查询
wildcard 通配符查询与前缀 prefix 查询不同的是它允许指定匹配的正则式。它使用标准的 shell 通配符
查询: ? 匹配任意字符, * 匹配 0 或多个字符。
#例:这个查询会匹配包含 W1F 7HW 和 W2F 8HW 的文档
$ GET /trade/address/_search
{
"query": {
"wildcard": {
"postcode": "W?F*HW" #? 匹配 1 和 2 , * 与空格及 7 和 8 匹配
}
}
}
regexp 正则式查询可以写出更复杂的模式
$ GET /trade/address/_search
{
"query": {
"regexp": {
"postcode": "W[0-9].+" #必须以 W 开头,紧跟 0 至 9 之间的任何一个数字,然后接一或多个其他字符
}
}
}
#注:
对有很多唯一词的字段执行 wildcard 和 regexp 查询可能会消耗非常多的资源,所以要避免使用左通配这样
的模式匹配(如: *foo 或 .*foo 这样的正则式)
prefix 、 wildcard 和 regexp 查询是基于词操作的,如果用来查询 analyzed 字段,它们会检查字段里面的
每个词,而不是将字段作为整体来处理。
比方说包含 “Quick brown fox” 的 title 字段会生成词: quick 、 brown 和 fox
可以匹配以下这个查询
{ "regexp": { "title": "br.*" }}
但是不会匹配以下两个查询
{ "regexp": { "title": "Qu.*" }} #在索引里的词是 quick 而不是 Quick
{ "regexp": { "title": "quick br*" }} #quick 和 brown 在词表中是分开的
4、查询时输入即搜索(即时搜索)
在 match_phrase 短语匹配查询中,它匹配相对顺序一致的所有指定词语,对于查询时的输入即搜索,可以使
用 match_phrase 的一种特殊形式, match_phrase_prefix 查询
{
"match_phrase_prefix" : {
"brand" : "johnnie walker bl"
}
}
这种查询的行为与 match_phrase 查询一致,不同的是它将查询字符串的最后一个词作为前缀使用
与 match_phrase 一样,match_phrase_prefix 也可以接受 slop 参数
{
"match_phrase_prefix" : {
"brand" : {
"query": "walker johnnie bl", #设置足够高的 slop 值使匹配时的词序有更大的灵活性
"slop": 10
}
}
}
通过设置 max_expansions 参数来限制前缀扩展的影响,一个合理的值是可能是 50
{
"match_phrase_prefix" : {
"brand" : {
"query": "johnnie walker bl",
"max_expansions": 50
}
}
}
参数 max_expansions 控制着可以与前缀匹配的词的数量,它会先查找第一个与前缀 bl 匹配的词,然后依次
查找搜集与之匹配的词(按字母顺序),直到没有更多可匹配的词或当数量超过 max_expansions 时结束
5、索引时输入即搜索
n-gram 可以看成一个在词语上 滑动窗口 , n 代表这个 “窗口” 的长度。
长度 1: [ q, u, i, c, k ]
长度 2: [ qu, ui, ic, ck ]
长度 3: [ qui, uic, ick ]
长度 4: [ quic, uick ]
长度 5: [ quick ]
1> 准备索引
配置一个自定义的 edge_ngram token 过滤器,称为 autocomplete_filter
{
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
}
}
2> 在自定义分析器 autocomplete 中使用上面这个 token 过滤器
{
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter" #自定义的 edge-ngram token 过滤器
]
}
}
}
这个分析器使用 standard 分词器将字符串拆分为独立的词,并且将它们都变成小写形式,然后为每个词生成
一个边界 n-gram
3> 完整流程
$ PUT /trade
{
"settings": {
"number_of_shards": 1,
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
}
}
4> 将分析器应用到具体字段
$ PUT /trade/_mapping/share
{
"my_type": {
"properties": {
"name": {
"type": "string",
"analyzer": "autocomplete"
}
}
}
}
5> 创建测试文档
$ POST /trade/share/_bulk
{ "index": { "_id": 1 }}
{ "name": "Brown foxes" }
{ "index": { "_id": 2 }}
{ "name": "Yellow furballs" }
6> 查询
$ GET /trade/share/_search
{
"query": {
"match": {
"name": "brown fo"
}
}
}
#返回值
{
"hits": [
{
"_id": "1",
"_score": 1.5753809,
"_source": {
"name": "Brown foxes"
}
},
{
"_id": "2",
"_score": 0.012520773,
"_source": {
"name": "Yellow furballs"
}
}
]
}
满足第二个文档,因为 furballs 是以 f 、 fu 、 fur 形式索引的
如果需要保证倒排索引表中包含边界 n-grams 的每个词,但是只想匹配用户输入的完整词组
( brown 和 fo ),可以通过在索引时使用 autocomplete 分析器,并在搜索时使用 standard 标准分析器来
实现这种想法,只要改变查询使用的搜索分析器 analyzer 参数即可
$ GET /trade/share/_search
{
"query": {
"match": {
"name": {
"query": "brown fo",
"analyzer": "standard" #覆盖了 name 字段 analyzer 的设置
}
}
}
}
也可以在映射中,为 name 字段分别指定 index_analyzer 和 search_analyzer
$ PUT /trade/share/_mapping
{
"my_type": {
"properties": {
"name": {
"type": "string",
"index_analyzer": "autocomplete", #在索引时,使用 autocomplete 分析器生成边界 n-grams 的每个词
"search_analyzer": "standard" #在搜索时,使用 standard 分析器只搜索用户输入的词
}
}
}
}