es 6.0 开始不推荐一个index下多个type的模式,并且会在 7.0 中完全移除。在 6.0 的index下是无法创建多个type的,type带来的字段类型冲突和检索效率下降的问题,导致了type会被移除。(5.x到6.x)_all字段也被舍弃了,使用 copy_to自定义联合字段。(5.x到6.x)type:text/keyword 来决定是否分词,index: true/false决定是否索引(2.x到5.x)analyzer来单独设定分词器(2.x到5.x)创建索引我们新建一个名news的索引:设定默认分词器为ik分词器用来处理中文使用默认名 _doc 定义 type关闭_source存储(用来验证 store 选项)title 不存储 author 不分词 content 存储PUT /news{ “settings”: { “number_of_shards”: 5, “number_of_replicas”: 1, “index”: { “analysis.analyzer.default.type” : “ik_smart” } }, “mappings”: { “_doc”: { “_source”: { “enabled”: false }, “properties”: { “news_id”: { “type”: “integer”, “index”: true }, “title”: { “type”: “text”, “store”: false }, “author”: { “type”: “keyword” }, “content”: { “type”: “text”, “store”: true }, “created_at”: { “type”: “date”, “format”: “yyyy-MM-dd hh:mm:ss” } } } }}# 查看创建的结构GET /news/_mapping验证分词器是否生效# 验证分词插件是否生效GET /_analyze{ “analyzer”: “ik_smart”, “text”: “我热爱祖国”}GET /_analyze{ “analyzer”: “ik_max_word”, “text”: “我热爱祖国”}# 索引的默认分词器GET /news/_analyze{ “text”: “我热爱祖国!”}# 指定字段 分词器将根据字段属性做相应分词处理# author 为 keyword 是不会做分词处理GET /news/_analyze{ “field”: “author” “text”: “我热爱祖国!”}# title 的分词结果GET /news/_analyze{ “field”: “title” “text”: “我热爱祖国!"}添加文档用于演示,后面的查询会以这些文档为例。POST /news/_doc{ “news_id”: 1, “title”: “我们一起学旺叫”, “author”: “才华横溢王大猫”, “content”: “我们一起学旺叫,一起旺旺旺旺旺,在你面撒个娇,哎呦旺旺旺旺旺,我的尾巴可劲儿摇”, “created_at”: “2019-03-26 11:55:20”}{ “news_id”: 2, “title”: “我们一起学猫叫”, “author”: “王大猫不会被分词”, “content”: “我们一起学猫叫,还是旺旺旺旺旺,在你面撒个娇,哎呦旺旺旺旺旺,我的尾巴可劲儿摇”, “created_at”: “2019-03-26 11:55:20”}{ “news_id”: 3, “title”: “实在编不出来了”, “author”: “王大猫”, “content”: “实在编不出来了,随便写点数据做测试吧,旺旺旺”, “created_at”: “2019-03-26 11:55:20”}检索数据match_all即无检索条件获取全部数据#无条件分页检索 以 news_id 排序GET /news/_doc/_search{ “query”: { “match_all”: {} }, “from”: 0, “size”: 2, “sort”: { “news_id”: “desc” }}因为我们关掉了_source字段,即 ES 只会对数据建立倒排索引,不会存储其原数据,所以结果里没有相关文档原数据内容。关掉的原因主要是想演示highlight机制。match普通检索,很多文章都说match查询会对查询内容进行分词,其实并不完全正确,match查询也要看检索的字段type类型,如果字段类型本身就是不分词的keyword(not_analyzed),那match就等同于term查询了。我们可以通过分词器explain一下字段会被如何处理:GET /news/_analyze{ “filed”: “title”, “text”: “我会被如何处理呢?分词?不分词?"}查询GET /news/_doc/_search{ “query”: { “match”: { “title”: “我们会被分词” } }, “highlight”: { “fields”: { “title”: {} } }}通过highlight我们可以将检索到的关键词以高亮的方式返回上下文内容,如果关闭了_source就得开启字段的store属性存储字段的原数据,这样才能做高亮处理,不然没有原内容了,也就没办法高亮关键词了multi_match对多个字段进行检索,比如我想查询title或content中有我们关键词的文档,如下即可:GET /news/_doc/_search{ “query”: { “multi_match”: { “query”: “我们是好人”, “fields”: [“title”, “content”] } }, “highlight”: { “fields”: { “title”: {}, “content”: {} } }}match_phrase这个需要认证理解一下,match_phrase,短语查询,何为短语查询呢?简单来说即被查询的文档字段中要包含查询内容被分词解析后的所有关键词,且关键词在文档中的分布距离差offset要满足slop设定的阈值。slop表征可以将关键词平移几次来满足在文档中的分布,如果slop足够的大,那么即便所有关键词在文档中分布的很离散,也是可以通过平移满足的。content: i love chinamatch_phrase: i chinaslop: 0//查不到 需要将 i china 的 china 关键词 slop 1 后变为 i - china 才能满足slop: 1//查得到测试实例# 先看下查询会被如何解析分词GET /news/_analyze{ “field”: “title”, “text”: “我们学”}# reponse{ “tokens”: [ { “token”: “我们”, “start_offset”: 0, “end_offset”: 2, “type”: “CN_WORD”, “position”: 0 }, { “token”: “学”, “start_offset”: 2, “end_offset”: 3, “type”: “CN_CHAR”, “position”: 1 } ]}# 再看下某文档的title是被怎样建立倒排索引的GET /news/_analyze{ “field”: “title”, “text”: “我们一起学旺叫”}# reponse{ “tokens”: [ { “token”: “我们”, “start_offset”: 0, “end_offset”: 2, “type”: “CN_WORD”, “position”: 0 }, { “token”: “一起”, “start_offset”: 2, “end_offset”: 4, “type”: “CN_WORD”, “position”: 1 }, { “token”: “学”, “start_offset”: 4, “end_offset”: 5, “type”: “CN_CHAR”, “position”: 2 }, … ]}注意position字段,只有slop的阈值大于两个不相邻的关键词的position差时,才能满足平移关键词至查询内容短语分布的位置条件。查询内容被分词为:[“我们”, “学”],而文档中[“我们”, “学”]两个关键字的距离为 1,所以,slop必须大于等于1,此文档才能被查询到。使用查询短语模式:GET /news/_doc/_search{ “query”: { “match_phrase”: { “title”: { “query”: “我们学”, “slop”: 1 } } }, “highlight”: { “fields”: { “title”: {} } }}查询结果:{ … { “_index”: “news”, “_type”: “_doc”, “_id”: “if-CuGkBddO9SrfVBoil”, “_score”: 0.37229446, “highlight”: { “title”: [ “<em>我们</em>一起<em>学</em>猫叫” ] } }, { “_index”: “news”, “_type”: “_doc”, “_id”: “iP-AuGkBddO9SrfVOIg3”, “_score”: 0.37229446, “highlight”: { “title”: [ “<em>我们</em>一起<em>学</em>旺叫” ] } } …}termterm要理解只是不对查询条件分词,作为一个关键词去检索索引。但文档存储时字段是否被分词建立索引由_mappings时设定了。可能有[“我们”, “一起”]两个索引,但并没有[“我们一起”]这个索引,查询不到。keyword类型的字段则存储时不分词,建立完整索引,查询时也不会对查询条件分词,是强一致性的。GET /news/_doc/_search{ “query”: { “term”: { “title”: “我们一起” } }, “highlight”: { “fields”: { “title”: {} } }}termsterms则是给定多个关键词,就好比人工分词{ “query”: { “terms”: { “title”: [“我们”, “一起”] } }, “highlight”: { “fields”: { “title”: {} } }}满足[“我们”, “一起”]任意关键字的文档都能被检索到。wildcardshell通配符查询: ? 一个字符 * 多个字符,查询倒排索引中符合pattern的关键词。查询有两个字符的关键词的文档{ “query”: { “wildcard”: { “title”: “??” } }, “highlight”: { “fields”: { “title”: {}, “content”: {} } }}prefix前缀查询,查询倒排索引中符合pattern的关键词。{ “query”: { “prefix”: { “title”: “我” } }, “highlight”: { “fields”: { “title”: {}, “content”: {} } }}regexp正则表达式查询,查询倒排索引中符合pattern的关键词。查询含有2 ~ 3 个字符的关键词的文档{ “query”: { “regexp”: { “title”: “.{2,3}” } }, “highlight”: { “fields”: { “title”: {}, “content”: {} } }}bool布尔查询通过 bool链接多个查询组合:must:必须全满足must_not:必须全不满足should:满足一个即可{ “query”: { “bool”: { “must”: { “match”: { “title”: “绝对要有我们” } }, “must_not”: { “term”: { “title”: “绝对不能有我” } }, “should”: [ { “match”: { “content”: “我们” } }, { “multi_match”: { “query”: “满足”, “fields”: [“title”, “content”] } }, { “match_phrase”: { “title”: “一个即可” } } ], “filter”: { “range”: { “created_at”: { “lt”: “2020-12-05 12:00:00”, “gt”: “2019-01-05 12:00:00” } } } } }, “highlight”: { “fields”: { “title”: {}, “content”: {} } }}filterfilter 通常情况下会配合match之类的使用,对符合查询条件的数据进行过滤。{ “query”: { “bool”: { “must”: { “match_all”: {} }, “filter”: { “range”: { “created_at”: { “lt”: “2020-12-05 12:00:00”, “gt”: “2017-12-05 12:00:00” } } } } }}或者单独使用{ “query”: { “constant_score” : { “filter”: { “range”: { “created_at”: { “lt”: “2020-12-05 12:00:00”, “gt”: “2017-12-05 12:00:00” } } } } }}多个过滤条件:2017-12-05 12:00:00 <= created_at < 2020-12-05 12:00:00 and news_id >= 2{ “query”: { “constant_score” : { “filter”: { “bool”: { “must”: [ { “range”: { “created_at”: { “lt”: “2020-12-05 12:00:00”, “gt”: “2017-12-05 12:00:00” } } }, { “range”: { “news_id”: { “gte”: 2 } } } ] } } } }}
...