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码农社区】,会定时推送各种干货: