二十二、Elasticsearch前缀匹配、通配符搜索和正则搜索

1、本章所讲内容好比SQL中的模糊查询

2、数据准备

PUT /my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "title" : {
          "type": "keyword"
        }
      }
    }
  }
}

准备三条数据

POST /my_index/my_type/1
{
  "title" : "C3D0-KD345"
}

POST /my_index/my_type/2
{
  "title" : "C3K5-DFG65"
}

POST /my_index/my_type/3
{
  "title" : "C4I8-UI365"
}

3、前缀匹配

类似于SQL中的右模糊。 like 'xxx%'

需求:上面已经插入了三条数据:

C3D0-KD345
C3K5-DFG65
C4I8-UI365

搜出以C3开头的document

GET /my_index/my_type/_search
{
  "query": {
    "prefix": {
      "title": {
        "value": "C3"
      }
    }
  }
}

结果:

{
  "took": 56,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1,
    "hits": [
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "2",
        "_score": 1,
        "_source": {
          "title": "C3K5-DFG65"
        }
      },
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "1",
        "_score": 1,
        "_source": {
          "title": "C3D0-KD345"
        }
      }
    ]
  }
}

4、前缀匹配的原理

从上面结果可以看出两条数据的score都是1,从而可知,prefix query不计算relevance score,与filter唯一的区别是filter会cache bitset

前缀越短,要处理的doc越多,性能越差,尽可能用长前缀搜索

问:为什么性能不好?原理是怎样的?
答:
假设有三个doc

doc1:C3-D0-KD345
doc2:C3-K5-DFG65
doc3:C4-I8-UI365

通过

GET /_analyze
{
  "text": "C3-D0-KD345",
  "analyzer": "standard"
}

分析出他的分词结果如下:

c3          doc1,doc2都有此term
d0
kd345
k5
dfg65
c4
i8
ui365

match性能是很高的,为什么?
C3 --》扫描倒排索引 --》一旦扫描到C3就可以停了。已经找到了,没必要继续搜索其他term了。比如这里第一个就是C3,那搜索的时候扫描完第一个term就停了,因为已经找到了。

prefix性能很低,为什么?

因为前缀搜索不分词,还是如下的term

C3-D0-KD345
C3-K5-DFG65
C4-I8-UI365

c3 --> 先扫描到了C3-D0-KD345,很棒,找到了一个前缀带c3的字符串 --> 还是要继续搜索的,因为后面还有一个C3-K5-DFG65,也许还有其他很多的前缀带c3的字符串 --> 你扫描到了一个前缀匹配的term,不能停,必须继续搜索 --> 直到扫描完整个的倒排索引,才能结束

所以prefix相对于match来讲性能很差。

5、通配符搜索

可完成SQL中的左模糊+右模糊+全模糊
跟前缀搜索类似,但是功能更加强大,但是性能依旧差,原理同prefix。

C3D0-KD345
C3K5-DFG65
C4I8-UI365

(1)搜索以C3开头的

GET /my_index/my_type/_search
{
  "query": {
    "wildcard": {
      "title": {
        "value": "C3?*"
      }
    }
  }
}

(2)搜索以C开头的第二个字符随意,第三个字符必须是K的,最后一个字符必须是5的doc

GET /my_index/my_type/_search
{
  "query": {
    "wildcard": {
      "title": {
        "value": "C?K*5"
      }
    }
  }
}

(3)搜索包含数字6的doc

GET /my_index/my_type/_search
{
  "query": {
    "wildcard": {
      "title": {
        "value": "*6*"
      }
    }
  }
}

?:任意字符
*:0个或任意多个字符

6、正则搜索

可完成SQL中的左模糊+右模糊+全模糊
跟前缀搜索类似,但是功能更加强大,但是性能依旧差,原理同prefix。

查看以C开头,第二个是随便1个数字,末尾是345的doc

GET /my_index/my_type/_search
{
  "query": {
    "regexp" : {
      "title" : "C[0-9].+345"
    }
  }
}

[0-9]:指定范围内的数字
[a-z]:指定范围内的字母
.:一个字符
+:前面的正则表达式可以出现一次或多次

若有兴趣,欢迎来加入群,【Java初学者学习交流群】:458430385,此群有Java开发人员、UI设计人员和前端工程师。有问必答,共同探讨学习,一起进步!
欢迎关注我的微信公众号【Java码农社区】,会定时推送各种干货:


二十二、Elasticsearch前缀匹配、通配符搜索和正则搜索_第1张图片
qrcode_for_gh_577b64e73701_258.jpg

你可能感兴趣的:(二十二、Elasticsearch前缀匹配、通配符搜索和正则搜索)