Elasticsearch笔记(5)

搜索机制

搜索的流程图如下:

搜索的流程图

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,字段中的词项顺序需要一致

match一phrase


match_phrase_prefix query


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)

FROM

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"

SDL:

{

  "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

  }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容