elasticsearch query string怎么支持elastic 查询特殊字符符

关于我,。
对这类话题感兴趣?欢迎发送邮件至
请支持原创&
es在查询时,可以指定搜索类型为QUERY_THEN_FETCH,QUERY_AND_FEATCH,DFS_QUERY_THEN_FEATCH和DFS_QUERY_AND_FEATCH。那么这4种搜索类型有什么区别?
分布式搜索背景介绍:
ES天生就是为分布式而生,但分布式有分布式的缺点。比如要搜索某个单词,但是数据却分别在5个分片(Shard)上面,这5个分片可能在5台主机上面。因为全文搜索天生就要排序(按照匹配度进行排名),但数据却在5个分片上,如何得到最后正确的排序呢?ES是这样做的,大概分两步。
step1、ES客户端会将这个搜索词同时向5个分片发起搜索请求,这叫Scatter,
step2、这5个分片基于本Shard独立完成搜索,然后将符合条件的结果全部返回,这一步叫Gather。
客户端将返回的结果进行重新排序和排名,最后返回给用户。也就是说,ES的一次搜索,是一次scatter/gather过程(这个跟mapreduce也很类似).
然而这其中有两个问题。
第一、数量问题。比如,用户需要搜索"双黄连",要求返回最符合条件的前10条。但在5个分片中,可能都存储着双黄连相关的数据。所以ES会向这5个分片都发出查询请求,并且要求每个分片都返回符合条件的10条记录。当ES得到返回的结果后,进行整体排序,然后取最符合条件的前10条返给用户。这种情况,ES5个shard最多会收到10*5=50条记录,这样返回给用户的结果数量会多于用户请求的数量。
第二、排名问题。上面搜索,每个分片计算分值都是基于自己的分片数据进行计算的。计算分值使用的词频率和其他信息都是基于自己的分片进行的,而ES进行整体排名是基于每个分片计算后的分值进行排序的,这就可能会导致排名不准确的问题。如果我们想更精确的控制排序,应该先将计算排序和排名相关的信息(词频率等)从5个分片收集上来,进行统一计算,然后使用整体的词频率去每个分片进行查询。
这两个问题,估计ES也没有什么较好的解决方法,最终把选择的权利交给用户,方法就是在搜索的时候指定query type。
1、query and fetch
向索引的所有分片(shard)都发出查询请求,各分片返回的时候把元素文档(document)和计算后的排名信息一起返回。这种搜索方式是最快的。因为相比下面的几种搜索方式,这种查询方法只需要去shard查询一次。但是各个shard返回的结果的数量之和可能是用户要求的size的n倍。
2、query then fetch(默认的搜索方式)
如果你搜索时,没有指定搜索方式,就是使用的这种搜索方式。这种搜索方式,大概分两个步骤,第一步,先向所有的shard发出请求,各分片只返回排序和排名相关的信息(注意,不包括文档document),然后按照各分片返回的分数进行重新排序和排名,取前size个文档。然后进行第二步,去相关的shard取document。这种方式返回的document与用户要求的size是相等的。
3、DFS query and fetch
这种方式比第一种方式多了一个初始化散发(initial scatter)步骤,有这一步,据说可以更精确控制搜索打分和排名。
4、DFS&query then fetch
比第2种方式多了一个初始化散发(initial scatter)步骤。
DSF是什么缩写?初始化散发是一个什么样的过程?
从es的官方网站我们可以指定,初始化散发其实就是在进行真正的查询之前,先把各个分片的词频率和文档频率收集一下,然后进行词搜索的时候,各分片依据全局的词频率和文档频率进行搜索和排名。显然如果使用DFS_QUERY_THEN_FETCH这种查询方式,效率是最低的,因为一个搜索,可能要请求3次分片。但,使用DFS方法,搜索精度应该是最高的。
至于DFS是什么缩写,没有找到相关资料,这个D可能是Distributed,F可能是frequency的缩写,至于S可能是Scatter的缩写,整个单词可能是分布式词频率和文档频率散发的缩写。
总结一下,从性能考虑QUERY_AND_FETCH是最快的,DFS_QUERY_THEN_FETCH是最慢的。从搜索的准确度来说,DFS要比非DFS的准确度更高。
参考资料:
阅读(...) 评论()[Elasticsearch] 部分匹配 (二) - 通配符及正则表达式查询
通配符和正则表达式查询
wildcard查询和prefix查询类似,也是一个基于词条的低级别查询。但是它能够让你指定一个模式(Pattern),而不是一个前缀(Prefix)。它使用标准的shell通配符:?用来匹配任意字符,*用来匹配零个或者多个字符。
以下查询能够匹配包含W1F 7HW和W2F 8HW的文档:
GET /my_index/address/_search
"query": {
"wildcard": {
"postcode": "W?F*HW"
假设现在你想匹配在W地域(Area)的所有邮政编码。使用前缀匹配时,以WC开头的邮政编码也会被匹配,在使用通配符查询时也会遇到类似的问题。我们只想匹配以W开头,紧跟着数字的邮政编码。使用regexp查询能够让你写下更复杂的模式:
GET /my_index/address/_search
"query": {
"regexp": {
"postcode": "W[0-9].+"
这个正则表达式的规定了词条需要以W开头,紧跟着一个0到9的数字,然后是一个或者多个其它字符。
wildcard和regexp查询的工作方式和prefix查询完全一样。它们也需要遍历倒排索引中的词条列表来找到所有的匹配词条,然后逐个词条地收集对应的文档ID。它们和prefix查询的唯一区别在于它们能够支持更加复杂的模式。
这也意味着使用它们存在相同的风险。对一个含有很多不同词条的字段运行这类查询是非常消耗资源的。避免使用一个以通配符开头的模式(比如,*foo或者正则表达式: .*foo)。
尽管对于前缀匹配,可以在索引期间准备你的数据让它更加高效,通配符和正则表达式匹配只能在查询期间被完成。虽然使用场景有限,但是这些查询也有它们的用武之地。
prefix,wildcard以及regexp查询基于词条进行操作。如果你在一个analyzed字段上使用了它们,它们会检查字段中的每个词条,而不是整个字段。
比如,假设我们的title字段中含有"Quick brown fox",它会产生词条quick,brown和fox。
这个查询能够匹配:
{ "regexp": { "title": "br.*" }}
而不会匹配:
{ "regexp": { "title": "Qu.*" }}
{ "regexp": { "title": "quick br*" }}7004人阅读
Elasticsearch(1)
参考官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html
& & & &query_string&:{
& & & & & & &default_field&:&name&,
& & & & & & &query&:&(this AND that) OR thu*&
这里只挑几个常用的参数说一下,其他的一般默认就够了
query: &需要查询的具体内容default_field: &查询的字段
默认是_all,即对所有字段进行查询。
支持多字段——&fields&&:&[&age&,&&name&],fields中只要有一个字段满足query的条件即可匹配查询。
支持一些简单的wildcard写法。比如fields:[“nam*”]即任何nam开头的字段,注意:如果field与query写在一起比如”query”:”name:obama”,要使用wildcard需要转义---&”query”:”nam\\*:obama”
当fields有多个的时候,会有另外一个参数:
use_dis_max:&true代表使用dis_max查询,false为bool查询
至于use_dis_max的用法:请参考http://blog.csdn.net/dm_vincent/article/details/
default_operator:默认运算符
& &有AND、OR,默认为OR。比如query里面的内容是”cat&dog”,两个短语以空格分开,如果default_operator参数为OR,那么只要字段内包含cat或者dog之一就可以匹配。
& 如果default_operator为AND,字段内必须同时包含cat和dog才可以匹配。与bool查询挺像的。
analyzer:分析器
& &用于分析query内容的分析器。&
& & & &这里需要注意的是query_string查询,query的内容会经过分析。其他的查询比如match查询也是会分析的,term查询会分析。打个比方:
& & & & & & & &PUT /animal { &name&: “DOG”}
& &因为分析器的原因,进行index的时候DOG会自动变成小写的dog.query_string与match查询因为查询的内容也会被分析,所以查询DOG时会自动判断为查询dog。而term查询不然,你查询DOG,
& & & 那么Elasticsearch就会去索引里 & &找DOG,很显然索引里只有小写的dog,你是无法查询成功的。
minimum_should_match: 最小匹配词条
& &比如query:”cat&dog&mouse”,这个配置项为2,那么只有字段里至少同时包含这三个中的任意两个才会匹配。需要注意的是,这个配置项只对default_operator为OR的时候生效。如果这个是AND,
& &那么cat&dog&mouse必须全部包含无论minimum_should_match为多少。
常见写法:
{“query”:{“query_string”:{“name:obama”}}}
name字段为obama
{“query”:{“query_string”:{“nam\\*:obama”}}}
存在一个nam开头的字段,值为obama
{“query”:{“query_string”:{“__missing__:name”}}}
name字段值为null的文档
{“query”:{“query_string”:{“__exists__:name”}}}
name字段值不为null的文档
{“query”:{“query_string”:{“name:(obama&OR&xidada)”}}}
name字段为Obama或者xidada的文档
注意这里!一定不要把这里的OR、AND与前面的混淆,minimum_should_match更需要注意运算符。如果这里全是OR,那么你可以用minimum_should_match,如果混用AND&OR&一定不要用这个参数。如果一定要用请把AND连接的用()括起来。
另外a&OR&b&OR&c.minimum_should_match为3代表&需要包含a&b&c三个。如果你用括号括起来(a&OR&b)&OR&c&那么括号内的将不是两个条件而是一个整体的条件,minimum_should_match为2&即代表需要同时包含a&b&c三个。
query的内容中支持?与*。?可以代替一个任意字符、&*可代表任意个字符(包括零个)。比如你要查询的内容很长,记不清了但是你记得末尾是tor,那么你只需要把query内容写成*tor即可
如果要在query的内容中使用正则表达式,在两端加上正斜杠/即可。比如name:/ob[am]{2}a/
支持的正则语法见:
这个是一个很实用的功能。你想搜obama可是你记不清了或者你错打成了obalv。没事,只要你在查询的时候加个~就不用担心了:&“query”:”name:obalv~”,你会惊喜的发现仍然可以搜到obama。
另外你可以在~后面加个数字来指定允许错误几个字母。默认以及最大都是2。比如你写成“query”:”name:obalv~1”,就只能允许一个错误,而你查询的内容错了两个字母,就无法搜到obama了。
range范围查询
具体语法为:[min&TO&max]&闭区间。{min&TO&max}开区间。不允许左闭右开!左开右闭!
date:[&TO&]
count:[1&TO&5]
count:[10&TO&*]
布尔运算符
这一章最开头提到了一些OR、AND。另外支持的运算符有+、-
+代表一定要出现:类似must。-代表一定不能包含:类似must_not
比如:&query&:&cat -dog +mouse& &这个就代表文档中必须包含mouse,必须不能包含dog
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:11616次
排名:千里之外ElasticSearch 常用的查询过滤语句 - 蝈蝈俊 - 博客园
posts - 485, comments - 160, trackbacks - 0, articles - 0
query 和& filter 的区别请看: & & Filter DSL & term 过滤 term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型):
{ "term": { "age":&&& 26&&&&&&&&&& }} { "term": { "date":&& "" }} { "term": { "public": true&&&&&&&& }} { "term": { "tag":&&& "full_text"& }} 完整的例子, hostname 字段完全匹配成
的数据: { & "query": { &&& "term": { &&&&& "hostname": "" &&& } & } } & terms 过滤 terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配: { &&& "terms": { &&&&&&& "tag": [ "search", "full_text", "nosql" ] &&&&&&& } } 完整的例子,所有http的状态是 302 、304 的, 由于ES中状态是数字类型的字段,所有这里我们可以直接这么写。: { & "query": { &&& "terms": { &&&&& "status": [ &&&&&&& 304, &&&&&&& 302 &&&&& ] &&& } & } } & range 过滤 range过滤允许我们按照指定范围查找一批数据: { &&& "range": { &&&&&&& "age": { &&&&&&&&&&& "gte":& 20, &&&&&&&&&&& "lt":&& 30 &&&&&&& } &&& } } 范围操作符包含:
gt :: 大于
gte:: 大于等于
lt :: 小于
lte:: 小于等于
一个完整的例子, 请求页面耗时大于1秒的数据,upstream_response_time 是 nginx 日志中的耗时,ES中是数字类型。 { & "query": { &&& "range": { &&&&& "upstream_response_time": { &&&&&&& "gt": 1 &&&&& } &&& } & } } & exists 和 missing 过滤 exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的IS_NULL条件.
{ &&& "exists":&& { &&&&&&& "field":&&& "title" &&& } }
这两个过滤只是针对已经查出一批数据来,但是想区分出某个字段是否存在的时候使用。 & bool 过滤 bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:
must :: 多个查询条件的完全匹配,相当于 and。
must_not :: 多个查询条件的相反匹配,相当于 not。
should :: 至少有一个查询条件匹配, 相当于 or。
这些参数可以分别继承一个过滤条件或者一个过滤条件的数组: { &&& "bool": { &&&&&&& "must":&&&& { "term": { "folder": "inbox" }}, &&&&&&& "must_not": { "term": { "tag":&&& "spam"& }}, &&&&&&& "should": [ &&&&&&&&&&&&&&&&&&& { "term": { "starred": true&& }}, &&&&&&&&&&&&&&&&&&& { "term": { "unread":& true&& }} &&&&&&& ] &&& } } & Query DSL & match_all 查询 可以查询到所有文档,是没有查询条件下的默认语句。 { &&& "match_all": {} } 此查询常用于合并过滤条件。 比如说你需要检索所有的邮箱,所有的文档相关性都是相同的,所以得到的_score为1. & match 查询 match查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。 如果你使用 match 查询一个全文本字段,它会在真正查询之前用分析器先分析match一下查询字符: { &&& "match": { &&&&&&& "tweet": "About Search" &&& } } 如果用match下指定了一个确切值,在遇到数字,日期,布尔值或者not_analyzed 的字符串时,它将为你搜索你给定的值: { "match": { "age":&&& 26&&&&&&&&&& }} { "match": { "date":&& "" }} { "match": { "public": true&&&&&&&& }} { "match": { "tag":&&& "full_text"& }} 提示: 做精确匹配搜索时,你最好用过滤语句,因为过滤语句可以缓存数据。 match查询只能就指定某个确切字段某个确切的值进行搜索,而你要做的就是为它指定正确的字段名以避免语法错误。 & multi_match 查询 multi_match查询允许你做match查询的基础上同时搜索多个字段,在多个字段中同时查一个: { &&& "multi_match": { &&&&&&& "query":&&& "full text search", &&&&&&& "fields":&& [ "title", "body" ] &&& } } & bool 查询 bool 查询与 bool 过滤相似,用于合并多个查询子句。不同的是,bool 过滤可以直接给出是否匹配成功, 而bool 查询要计算每一个查询子句的 _score (相关性分值)。
must:: 查询指定文档一定要被包含。
must_not:: 查询指定文档一定不要被包含。
should:: 查询指定文档,有则可以为文档相关性加分。
以下查询将会找到 title 字段中包含 "how to make millions",并且 "tag" 字段没有被标为 spam。 如果有标识为 "starred" 或者发布日期为2014年之前,那么这些匹配的文档将比同类网站等级高: { &&& "bool": { &&&&&&& "must":&&&& { "match": { "title": "how to make millions" }}, &&&&&&& "must_not": { "match": { "tag":&& "spam" }}, &&&&&&& "should": [ &&&&&&&&&&& { "match": { "tag": "starred" }}, &&&&&&&&&&& { "range": { "date": { "gte": "" }}} &&&&&&& ] &&& } } 提示: 如果bool 查询下没有must子句,那至少应该有一个should子句。但是 如果有must子句,那么没有should子句也可以进行查询。 上面内容来自: & & ElasticSearch 查询(match和term)
wildcards 查询 使用标准的shell通配符查询 参考:
以下查询能够匹配包含W1F 7HW和W2F 8HW的文档:
GET /my_index/address/_search { &&& "query": { &&&&&&& "wildcard": { &&&&&&&&&&& "postcode": "W?F*HW" &&&&&&& } &&& } } 又比如下面查询 hostname 匹配下面shell通配符的: { & "query": { &&& "wildcard": { &&&&& "hostname": "wxopen*" &&& } & } } regexp 查询 假设您只想匹配以W开头,紧跟着数字的邮政编码。使用regexp查询能够让你写下更复杂的模式:
GET /my_index/address/_search { &&& "query": { &&&&&&& "regexp": { &&&&&&&&&&& "postcode": "W[0-9].+" &&&&&&& } &&& } } 这个正则表达式的规定了词条需要以W开头,紧跟着一个0到9的数字,然后是一个或者多个其它字符。 下面例子是所有以 wxopen 开头的正则 { & "query": { &&& "regexp": { &&&&& "hostname": "wxopen.*" &&& } & } } 参考:
prefix 查询 以什么字符开头的,可以更简单地用 prefix,如下面的例子: { & "query": { &&& "prefix": { &&&&& "hostname": "wxopen" &&& } & } } 参考 : & & 更多的查询命令,可以看:
& 短语匹配(Phrase Matching) 当你需要寻找邻近的几个单词时,你会使用match_phrase查询:GET /my_index/my_type/_search
"query": {
"match_phrase": {
"title": "quick brown fox"
}和match查询类似,match_phrase查询首先解析查询字符串来产生一个词条列表。然后会搜索所有的词条,但只保留含有了所有搜索词条的文档,并且词条的位置要邻接。一个针对短语quick fox的查询不会匹配我们的任何文档,因为没有文档含有邻接在一起的quick和box词条。
match_phrase查询也可以写成类型为phrase的match查询:"match": {
"title": {
"query": "quick brown fox",}

我要回帖

更多关于 elastic query string 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信