添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
搜索的流程图

1,文档写入ES的时候,ES中会存储两份数据。一份是文档的原始数据,即_source中存储的信息。另一份是通过分词、过滤等一系列动作之后生成的倒排索引文件,该文件记录了词项和文档的对应关系。

2,用户对文档进行搜索,ES接受到用户的关键词之后到倒排索引中取查找,通过倒排记录表查找到关键词对应的文档,然后在通过评分、高亮、排序等处理,返回给用户。

3,搜索机制解决的是相关度的问题。用户输入一个查询,ES通过计算关键词和文档之间的相关度,按照评分排序后返回相关度最高的文档给用户。

搜索过程

索引的创建、字段映射、文档的导入等工作参考前文,此处略过。

ES中有了数据就可以进行下一步的搜索了。

ES中的restful的查询语句要封装成json对象的形式,称为查询DSL语句。

例如查看books索引的全部数据的DSL语句如下:

get books/_search

"query":{

"match_all":{}

match_all query 会返回所有的文档,文档的评分都是1。可以简写为

get books/_search

下面以term query(精确匹配) 为例子进行讲解。

term 查询用来查询包含指定词项的文档。 term 查询不被解析,只有查询项和文档中的词精确匹配到该文档才会被索引到。应用场景为查询需要精确匹配的需求。

例如查询title中含有“思想”的文档,DSL语句如下:

GET books/_search

"from":"0" //从哪条开始

"size":"100" //返回的条数”

"_source":["title","price"], //指定返回的字段,如果不指定,默认返回所有的字段

"min_score":"0.6" //最下评分过滤机制,只有评分大于0.6的文档才会返回。

"query":{

"term":{"title":"思想"}

//高亮查询关键字

"highlight":{

"fields":{

"title":{}

全文索引

match query

match query 会对查询语句进行分词,分词后查询语句中的任何一个词被匹配到,那么文档就会被索引到。如果想匹配所有关键词的文档,可以用and关键字连接。例如:

GET books/_search

"query":{

"match":{

"title":{

"query":"java"

"operator":"and"


match一phrase query

match-phrase query 查询首先会把查询语句分词,分词器可以自定义。同时文档需要满足一下两个条件文档才会被索引到

1,分词后的字段要全部出现在目标字段中

2,字段中的词项顺序需要一致


multi一match query

multi一match query  是match的升级版,用于搜索多个字段。例如查询语句为:“Java编程”,

查询域为title和description。查询DSL语句如下:

GET books/_search

"query":{

multi-match:{

query:"Java编程"

//指定查询的字段,*_name 为通配符的形式

fields:["title","description","*_name"]

common_terms query

common terms query 是一种在不牺牲性能的情况下替代停用词提高搜索准确率和召回率

的方案。

query_string query

query string query 是与Lucene 查询语句的语法结合非常紧密的一种查询,允许在一个查

询语句中使用多个特殊条件关键字( 如:AND|OR|NOT ) 对多个字段进行查询,建议熟悉

Lucene 查询语法的用户去使用。

词项查询


term query

上文讲过了,不在赘述

terms 查询

如下,查询北京和西安的数据

"query": {

"terms": {

"city": [

"北京",

range query

range 用于检索某一个范围内的文档。比如说价格50到100的书籍信息等。range有四个参数

gt:大于(>),查询范围的最小值,不包含临界值

gte: 大于等于(>=)。查询范围最小值,包含临界值。

lt: 小于(<)。查询范围的上界,不包含临界值。

lte:小于等于(<=)

查询价格50到100的书籍

GET books/_search

query:{

"range":{

"price":{

"gt":50,

"lte":100


exists query

返回字段中至少有一个非空值的文档。如:

"query": {

"exists": {

"field": "ownerName"

返回结果ownerName不为空的文档。

prefix query

prefix 查询用于查询某个字段中以给定前缀开始的文档,比如查询title 中含有以java 为前

缀的关键词的文档,那么含有java javascript javaee 等所有以java 开头关键词的文档都会被

匹配。如

"query": {

"prefix": {

"title": "Java"

wildcard query

通配符查询。支持单通配符和多通配符的形式。?用来一个字符,*用来匹配一个或者是多个字符。如:

"query": {

"wildcard": {

"title": "Java*"


regexp query

正则匹配。例如需要匹配以W 开头紧跟着数字的邮政编码:

"query": {

"regexp": {

"postcode": ""W[0-9].*"

fuzzy query

编辑距离又称Levenshtein 距离,是指两个字串之间,由一个转成另一个所需的最少编辑

操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

fuzzy 查询就是通过计算词项与文档的编辑距离来得到结果的,但是使用fozzy 查询需要消耗

的资源比较大,查询效率不高,适用于需要模糊查询的场景。举例如下,用户在输入查询关键

词时不小心把“javascript ” 拼成“javascritp ” ,在存在拼写错误的情况下使用模糊查询仍然可

以搜索到含有“javascript ” 的文档,查询语句如下:

"query": {

"fuzzy ": {

"title": "javascript "


type query

type query 用于查询具有指定类型的文档。例如查询Elasticsearch 中type 为IT 的文档,查

询语句如下:

"query": {

"type": {

"value": "IT"


ids query

ids query 用于查询具有指定id 的文档。。例如,查询类型为IT, id 为1 、3 、5

的文档,查询语句如下:

"query": {

"ids": {

"type": "IT",

"values":["1","3","5"]


复合查询

复合查询就是把一些简单查询组合在一起实现更复杂的查询需求,除此之外复合查询还

可以控制另外一个查询的行为。

constan_score


constant score query 可以包装一个其他类型的查询,并返回匹配过滤器中的查询条件且具

有相同评分的文档。下面的查询语句会返回title 字段中含有关键词“java ” 的文档,所有文档

的评分都是1.2:

"query": {

"constantscore": {

"filter":{

"term":{"title":"java"}

"boost":"1.2"

bool

bool查询可以把任意多个简单查询组合在一起。使用must、should、must_not、filter选项来表达各个简单查询之间的逻辑组合关系。每个选项都可以出现0次或者是多次。

must:文档必须匹配must选项下的查询条件。相当于逻辑运算的and

should:文档可以匹配should选项下的查询条件也可以不匹配。相当于逻辑运算的or。

must_not:于must相反。匹配到must_not查询条件的文档不会被返回。相当于逻辑运算的not

filter:功能和must类似。区别在于filter只起到过滤的作用,不对文档进行评分。

假设要查询title 中包含关键词java, 并且price 不能高于70, description 可以包含也可以

不包含虚拟机的书籍, 构造bool 查询语句如下:

GET books/ search

"query": {

"bool": {

"minimum—should一match": 1,}

"must": {

"match": { "title": "java"}}

"should": [

{"match": { "description": " 虚拟机" }}]

must_not": {

"range": {"price": {"gte": 70}}


dis_max

dis max与bool query 有一定联系也有一定区别,dis max query 支持多并发查询。

可返回与任意查询条件子句匹配的任何文档类型。与bool 查询可以将所有匹配查询的分数相

结合使的方式不同,dis 查询只使用最佳匹配查询条件的分数

fonction_score

fonction_score query 可以修改查询的文档得分,这个查询在有些情况下非常有用,比如通

过评分函数计算文档得分代价较高,可以改用过滤器加自定义评分函数的方式来取代传统的评

分方式。

使用fiinction score query , 用户需要定义一个查询和一至多个评分函数,评分函数会对查

询到的每个文档分别计算得分。

boosting

boosting 查询用于需要对两个查询的评分进行调整的场景,boosting 查询会把两个查询封

装在一起并降低其中一个查询的评分

indices

indices query 适用于需要在多个索引之间进行查询的场景,它允许指定一个索引名字列表

和内部查询。indices query 中有query 和no match query 两部分,query 中用于搜索指定索引

列表中的文档,no_match_query 中的查询条件用于搜索指定索引列表之外的文档。

嵌套查询

在Elasticsearch 这样的分布式系统中执行全SQL 风格的连接查询代价昂贵,是不可行的。

相应地,为了实现水平规模地扩展,Elasticsearch 提供了以下两种形式的join:

nested query (嵌套查询)

文档中可能包含嵌套类型的字段,这些字段用来索引一些数组对象,每个对象都可以作为

一条独立的文档被查询出来。

has child query (有子查询)和has_parent query (有父查询)

父子关系可以存在单个的索引的两个类型的文档之间。has_child 查询将返回其子文档能满

足特定查询的父文档,而has_parent 则返回其父文档能满足特定查询的子文档。


has_child

现在有两个索引:员工employee和城市(branch)。类似于数据的两张表。在ES中,员工是child type ,城市是parent type 。需要在映射中声明如下:

PUT /company

"mappings": {

"branch": {},

"employee” {"_parent": { "type": "branch"}}

通过子文档查询父文档需要使用has_child查询。例如,搜索1980 年以后出生的员工所在的

城市。

GET company/branch/_search

"query": {

"has_child": {

"type": "employee",

"query": {

"range": {"birthday": {"gte": "1980-01-01’ }}


has_parent

通过父文档查询子文档使用has_parent 查询。比如,搜索哪些employee 工作在UK, 查询

命令如下:

GET /company/employee/_search

"query": {

"has_parent": {

"paren_type": "branch",

"query": {"match": {"country": "UK"}}


位置查询

Elasticsearch 可以对地理位置点geo_point 类型和地理位置形状geo_shape 类型的数据进行

搜索。

geo_distance、geo_boundin_box、geo_polygon、geo_shape等。需要的时候可以具体的查询API。

特殊查询

more_like_this

more_like_this query 可以查询和提供文本类似的文档,通常用于近似文本的推荐等场景。

script

Elasticsearch 支持使用脚本进行查询。

搜索高亮(略)

搜索排序

默认排序

Elasticsearch 是按照查询和文档的相关度进行排序的,默认按评分降序排序。

对于match_all query 而言,由于只返回所有文档,不需要评分,文档的顺序为添加文档的

顺序。如果需要改变match_all query 的文档返回顺序,可以对_doc 进行排序。例如,返回最

后添加的那条文档, 可以对_doc 降序排序,设置返回文档条数为1 。

多字段排序

如按照价格降序排序,在根据年份升序排序。

GET books/ search

"sort": [

{"price": { "order": "desc"} },

{"year": {"order": "asc"}}]

分片影响评分

ES是在每一个分片上进行单独评分的,分片的数量会影响到评分的结果。。同时,分词器也会

影响评分,原因是使用不同的分词器会使倒排索引中的词项数发生改变,最终影响评分。



示例是一个SQL和SDL对应的关系

SELECT

COUNT(1)

table

WHERE order_type = 'GUARANTEE'

AND STATUS IN (

'FAILED',

'SUCCEEDED',

'REFUNDED',

'UNTESTED',

'UNTRANSFERED',

'TRANSFERED',

'SETTLED',

'APPLYREFUND'

AND  id = 306472658

AND time >= "2019-01-01 00:00:00"

AND time <= "2019-03-31 23:59:59"

"bool" : {

"must" : [

"term" : {

"id" : {

"value" : "306472658",

"boost" : 1.0

"term" : {

"order_type" : {

"value" : "GUARANTEE",

"boost" : 1.0

"range" : {

"time" : {

"from" : "20190101000000",

"to" : null,

"include_lower" : true,

"include_upper" : true,

"boost" : 1.0

"range" : {

"time" : {

"from" : null,

"to" : "20190331235959",

"include_lower" : true,

"include_upper" : true,

"boost" : 1.0

"terms" : {

"status" : [

"FAILED",

"SUCCEEDED",

"REFUNDED",

"UNTESTED",

"UNTRANSFERED",

"TRANSFERED",

"SETTLED",

"APPLYREFUND"

"boost" : 1.0

"disable_coord" : false,

"adjust_pure_negative" : true,

"boost" : 1.0

最后编辑于:2019-03-08 17:20