Elasticsearch【正则搜索】分析&实践
在ES中有很多使用不是很频繁的查询,可以达到一些特殊的效果。比如基于行为路径的漏斗模型。本篇就从使用上讲述一下正则表达式查询的用法。
Regexp Query
regexp允许使用正则表达式进行term查询.注意regexp如果使用不正确,会给服务器带来很严重的性能压力。比如.*开头的查询,将会匹配所有的倒排索引中的关键字,这几乎相当于全表扫描,会很慢。因此如果可以的话,最好在使用正则前,加上匹配的前缀。在正则中如果使用.*?
或者+
都会降低查询的性能。
注意:是term查询,也就是说这个查询不能跨term。
举个简单的例子:
GET /_search
{
"query": {
"regexp":{
"name.first": "s.*y"
}
}
}
正则支持的一些标准的用法:
搜索关键词的一部分
如果给定的term是abcde
ab.* 可以匹配
abcd 不可以匹配
也支持使用^
或者$
来指定开头或者结尾。
允许特殊字符
一些特殊字符是需要转义的,比如:
. ? + * | { } [ ] ( ) " \ # @ & < > ~
如果想要搜索某个固定的词,也可以加上双引号。
匹配任何字符
.
可以匹配任意字符,比如
ab...
a.c.e
这几个都可以匹配abcde
匹配一个或者多个
使用+
表示匹配一个或者多个字符
a+b+ # match
aa+bb+ # match
a+.+ # match
aa+bbb+ # match
上面这些都可以匹配aaabbb
匹配零个或者多个
a*b* # match
a*b*c* # match
.*bbb.* # match
aaa*bbb* # match
上面这些都可以匹配aaabbb
匹配另个或者一个
aaa?bbb? # match
aaaa?bbbb? # match
.....?.? # match
aa?bb? # no match
上面这些都可以匹配aaabbb
支持匹配次数
使用{}
支持匹配指定的最小值和最大值区间
{5} # repeat exactly 5 times
{2,5} # repeat at least twice and at most 5 times
{2,} # repeat at least twice
比如对于字符串:
a{3}b{3} # match
a{2,4}b{2,4} # match
a{2,}b{2,} # match
.{3}.{3} # match
a{4}b{4} # no match
a{4,6}b{4,6} # no match
a{4,}b{4,} # no match
捕获组
对于字符串ababab
(ab)+ # match
ab(ab)+ # match
(..)+ # match
(...)+ # no match
(ab)* # match
abab(ab)? # match
ab(ab)? # no match
(ab){3} # match
(ab){1,2} # no match
选择运算符
支持或操作的匹配,注意这里默认都是最长匹配的。
aabb|bbaa # match
aacc|bb # no match
aa(cc|bb) # match
a+|b+ # no match
a+b+|b+a+ # match
a+(b|c)+ # match
字符匹配
支持在[]
中进行字符匹配,^
代表非的意思
[abc] # 'a' or 'b' or 'c'
[a-c] # 'a' or 'b' or 'c'
[-abc] # '-' or 'a' or 'b' or 'c'
[abc\-] # '-' or 'a' or 'b' or 'c'
[^abc] # any character except 'a' or 'b' or 'c'
[^a-c] # any character except 'a' or 'b' or 'c'
[^-abc] # any character except '-' or 'a' or 'b' or 'c'
[^abc\-] # any character except '-' or 'a' or 'b' or 'c'
其中-
代表的范围匹配。
可选的匹配符
在正则表达式中也支持一些特殊的操作符,可以使用flags字段控制是否开启。
Complement
这个表示正则表示匹配一段字符串,比如ab~cd
意思是:a开头,后面是b,然后是一堆非c的字符串,最后以d结尾。比如字符串abcdef
ab~df # match
ab~cf # match
ab~cdef # no match
a~(cb)def # match
a~(bc)def # no match
Interval
interval选项支持数值的范围,比如字符串foo80
:
foo<1-100> # match
foo<01-100> # match
foo<001-100> # no match
Intersection
使用&
可以实现多个匹配的连接,比如字符串aaabbb
:
aaa.+&.+bbb # match
aaa&bbb # no match
Any
使用@
,可以匹配任意的字符串
实践
首先创建索引:
PUT test
然后创建映射:
PUT test/_mapping/test
{
"properties": {
"a": {
"type": "string",
"index":"not_analyzed"
},
"b":{
"type":"string"
}
}
}
添加一条数据:
PUT test/test/1
{
"a":"a,b,c","b":"a,b,c"
}
先来分析一下,a,b,c
被默认分析成了什么?
POST test/_analyze
{
"analyzer": "standard",
"text": "a,b,c"
}
返回内容:
{
"tokens": [
{
"token": "a",
"start_offset": 0,
"end_offset": 1,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "b",
"start_offset": 2,
"end_offset": 3,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "c",
"start_offset": 4,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 2
}
]
}
然后查询一下:
POST /test/test/_search?pretty
{
"query":{
"regexp":{
"a": "a.*b.*"
}
}
}
返回
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "test",
"_type": "test",
"_id": "1",
"_score": 1,
"_source": {
"a": "a,b,c",
"b": "a,b,c"
}
}
]
}
}
再换成b字段试试:
POST /test/test/_search?pretty
{
"query":{
"regexp":{
"b": "a.*b.*"
}
}
}
返回
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": []
}
}
这是为什么呢?
因为整个regexp查询是应用到一个词上的,针对某个词,搜索a.*b.*
,a字段由于不分词,它的词是整个的a.b.c
;b字段经过分词,他的词是a
和b
和c
三个独立的词,因此针对a字段的正则搜索可以查询到结果;但是针对b字段却搜索不到。
归纳起来,还是需要好好理解分词在搜索引擎中的作用才行。
参考
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html
Elasticsearch【正则搜索】分析&实践的更多相关文章
- fluentd结合kibana、elasticsearch实时搜索分析hadoop集群日志<转>
转自 http://blog.csdn.net/jiedushi/article/details/12003171 Fluentd是一个开源收集事件和日志系统,它目前提供150+扩展插件让你存储大数据 ...
- 基于 Kafka 的实时数仓在搜索的实践应用
一.概述 Apache Kafka 发展至今,已经是一个很成熟的消息队列组件了,也是大数据生态圈中不可或缺的一员.Apache Kafka 社区非常的活跃,通过社区成员不断的贡献代码和迭代项目,使得 ...
- Elasticsearch源码分析 - 源码构建
原文地址:https://mp.weixin.qq.com/s?__biz=MzU2Njg5Nzk0NQ==&mid=2247483694&idx=1&sn=bd03afe5a ...
- elasticsearch源码分析之search模块(server端)
elasticsearch源码分析之search模块(server端) 继续接着上一篇的来说啊,当client端将search的请求发送到某一个node之后,剩下的事情就是server端来处理了,具体 ...
- elasticsearch源码分析之search模块(client端)
elasticsearch源码分析之search模块(client端) 注意,我这里所说的都是通过rest api来做的搜索,所以对于接收到请求的节点,我姑且将之称之为client端,其主要的功能我们 ...
- Elasticsearch集成Hadoop最佳实践.pdf(内含目录)
Elasticsearch服务器开发(第2版) 介绍: ElasticSearch是一个开源的分布式搜索引擎,具有高可靠性,支持非常多的企业级搜索用例.ElasticsearchHadoop作为一个完 ...
- Elasticsearch分布式搜索
ElasticSearch之介绍 一 Elasticsearch产生背景 1.1 大规模数据如何检索 如:当系统数据量上了10亿.100亿条的时候,我们在做系统架构的时候通常会从以下角度去考虑问题:1 ...
- 十九种Elasticsearch字符串搜索方式终极介绍
前言 刚开始接触Elasticsearch的时候被Elasticsearch的搜索功能搞得晕头转向,每次想在Kibana里面查询某个字段的时候,查出来的结果经常不是自己想要的,然而又不知道问题出在了哪 ...
- 腾讯健康码16亿亮码背后的Elasticsearch系统调优实践【>>戳文章免费体验Elasticsearch服务30天】
[活动]Elasticsearch Service免费体验馆>>Elasticsearch Service新用户特惠狂欢低至4折>>Elasticsearch Service企 ...
随机推荐
- 手动的写一个structs
为了更好的学习框架的运行机制,这里开始学习框架之前,介绍一个简单的自定义的框架. 需求: 登录:id:aaa,pwd:888登录成功之后,跳转到,index.jsp页面并显示,欢迎你,aaa 注册,页 ...
- AE + GDAL实现影像按标准图幅分割(下)
在上篇实现了遥感影像的切割,本篇讲切割前的准备.主要分为以下几步: (1)将影像的投影坐标转换为地理坐标,以便于之后的图幅划分.AE坐标转换函数如下 private bool Proj2Geo(ISp ...
- java数组、java.lang.String、java.util.Arrays、java.lang.Object的toString()方法和equals()方法详解
public class Test { public static void main(String[] args) { int[] a = {1, 2, 4, 6}; int[] b = a; in ...
- Memcache存储机制与指令汇总
1.memcache基本简介 memcached是高性能的分布式内存缓存服务器.一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度.提高可扩展性. Memcach ...
- 【C++】浅谈三大特性之一继承(三)
四,派生类的六个默认成员函数 在继承关系里,如果我们没有显示的定义这六个成员函数,则编译系统会在适合场合为我们自动合成. 继承关系中构造函数和析构函数的调用顺序: class B { public: ...
- MyBatis使用statementType="STATEMENT"
statementType="STATEMENT"是使用非预编译,现在我需要动态传人表名和字段名,所以需要用STATEMENT,使用之后所有变量取值都要改成${xxxx},而不是# ...
- android Instrumentoation 问答
android Instrumentoation 问答 1.instrumentation是执行application instrumentation代码的基类.当应用程序运行的时候instrum ...
- 第一个python爬虫程序
1.安装Python环境 官网https://www.python.org/下载与操作系统匹配的安装程序,安装并配置环境变量 2.IntelliJ Idea安装Python插件 我用的idea,在工具 ...
- scss的初级学习随笔小计
$white: #fff;$three: #333;$six: #666;$nine: #999;$red: #fff;$orange: #f63;$yellow: #fc0;$opcity: rgb ...
- Python 安装虚拟环境
写在前面: 安装指南是在 Ubuntu 下面操作的.不同的 Linux 版本,安装指令不同.所以,该指南的某些指令对于像 CentOS 等非 Ubuntu 系统不适用. 为什么需要使用虚拟环境? 虚拟 ...