ElasticSearch的索引机制 和 query dsl语法的使用

ElasticSearch的数据类型

text 被用来索引长文本,建立索引钱会将这些文本进行分词
keyword 不需要分词,可以被用来检索过滤、排序、聚合
数学类型:long integer short byte doucle float
日期类型: date
布尔类型:boolean
二进制:binary
数组类型
对象类型 object
等等基本数据类型,还有许多特定类型如地理位置、Ipv4等等 不过多介绍

倒排索引

ElasticSearch使用一种称为倒排索引的结构,它适用于快速的全文检索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每一个词,都有一个包含它的文档列表

示例:

id 内容
1 小明
2 小丽
3 小黑

用分词器将内容自动切分成单词序列,每个文档就转换为由单词序列构成的数据流,需要对每个不通给的单词赋予唯一的单词编号,同事记录下哪些文档包含这个单词,由此我们可以得到每个单词的倒排列表,如下

id 单词 倒排列表
1 1,2,3
2 1
3 2
4 3

倒排列表中可以记录单词出现的频率,即该单词在某个文档中出现次数,如下表格

id 单词 倒排列表
1 (1;1),(2;1),(3;1)
2 (1;1)
3 (2;1)
4 (3;1)

倒排列表中还可以记录单词在某个文档中出现的文职信息,如
(1,<1>,1) 表示单词在id为1的文档中出现过一次,位置为1

倒排索引建立规则

Hello 和hello,用户会认为他们是相同的词
dog和dogs 他们有相同的词根
jumped和leap 没有相同的词根,但是他们的意思相近,是同义词
以上情况,应该都能被同一种搜索条件搜索到
所以,在建立倒排所以的时候,es会使用标准化规则,以确保上面的例子都能被搜索到。

分词器

从一串文本中且分出一个一个的词条,并对没个词条进行标准化。包括三部分:
1.charactre fiter,分词之前的预处理,过滤掉HTML标签,特殊符号转换等
2.tokenizer,分词
3.token filter,标准化(单复数、大小写、同义词等)

内置分词器

1.standard分词器(默认分词器),他会将词汇转换成小写形式,并去除停用词和标点符号,支持中文,采用的方法为单字切分
2.simpl分词器,首先会通过非字母字符来分割文本信息,将词汇单元统一为小写形式,该分词器会去掉数学类型的字符
3.whitespace分词器,仅去掉空格,对字符没有lowcase化,不支持中文,不对生成的词汇单元进行其他标准化处理
4.language分词器,特定语言分词器,不支持中文

kibana使用

创建索引

PUT  /lib/ 
{
	"settings":{
		"index":{
			"number_of_shards": 3,
			"number_of_replicas": 0
		}
	}
}

/lib/ --索引的名称 ,number_of_shards – 分片的数量,number_of_replicas – 备份的数量
//如果不设置settings 则使用默认配置 number_of_shards为5 ,number_of_replicas为1

PUT /lib/user/1
{
“first_name”:“xiaowang”,
“last_name”:“laowang”,
“age”:55,
“about”:“I like to collect rockalbums”,
“interrests”:[“music”]
}
//在索引lib下添加类型为user,id为1的一条数据
如果不指定id,则使用POST,id由es服务器自动生成

查看索引

查看索引配置
GET /lib/_settgins
查看所有索引的配置
GET /_all/_settgins
查看指定id的数据
GET /lib/user/1
//指定显示结果集字段
GET /lib/user/1?_source=age,about

更新索引

多次put会覆盖掉前一次
如果要更新指定字段,则需要post
POST /lib/user/1/_update
{
“doc”:{
“age”:56
}
}

删除

DELETE /lib/user/1 --删除指定数据

DELETE /lib2/ --删除索引

批量获取

GET /_mget
{
“docs”:[
{
“_index”:“lib”,
“_type”:“user”,
“_id”:1
},
{
“_index”:“lib”,
“_type”:“user”,
“_id”:2
}
]
}
//分别指定不同的字段
GET /_mget
{
“docs”:[
{
“_index”:“lib”,
“_type”:“user”,
“_id”:1,
“_source”:[“age”,“intersts”]
},
{
“_index”:“lib”,
“_type”:“user”,
“_id”:2,
“_source”:“intersts”
}
]
}
//简化写法,也可以单独指定
GET /lib/user/_mget
{
“docs”:[
{
“_id”:1
},
{
“type”:“user2”,
“_id”:2
}
]
}
//如果是同类型的批量获取 还可以再次简化
GET /lib/user/_mget
{
“ids”:[“1”,“2”]
}
//搜索 排序
GET /lib/user/_search?q=last_name:laoli&sort=age:desc

query查询

term查询

//复杂 条件查询
GET /lib/user/_search
{
“query”:{
“terms”:{
“interests”:[“music”]
}
}
}
//分页
GET /lib/user/_search
{
“from”:0,
“size”:2,
“query”:{
“terms”:{
“interests”:[“music”]
}
}
}
//如果需要显示版本号在上边的json中加入"version":true

match查询

GET /lib/user/_search
{

"query":{
		"match":{
				"name":"zhaoliu  tianqi"
			}
 }

}
会查询出包含zhaoliu、tianqi的所有数据。term和match的主要区别在于,term不使用分词器,对值进行完全匹配,match会对查找条件进行分词,匹配倒排索引。
精确查找使用使用term,匹配查找使用match

//查询全部
GET /lib/user/_search
{
“query”:{
“match_all”: {}
}
}
//多filed查询
GET /lib/user/_search
{
“query”:{
“multi_match”:{
“query”:“laowang,xiaoli”,
“fields”:["last_name,“first_name”]
}
}
}
//短语匹配,匹配指定字段 相当于模糊查询
GET /lib/user/_search
{

"query":{
		"match_phrase":{
		  "last_name":"laowang shi shei"
		}
 }

}
//指定结果集
GET /lib/user/_search
{

"query":{
		"match_all":{}
 },
 "_source":["last_name","age"]

}
或者
GET /lib/user/_search
{

"query":{
		"match_all":{}
 },
 "_source":{
   "includes":"*name",
   "excludes": ["age"]
 }

}
//排序
GET /lib/user/_search
{
“query”:{
“match_all”:{}
},
“sort”:{
“age”:{
“order”:“asc”
}
}
}
//查询指定日期

GET /lib/user/_search
{
“query”:{
“range”:{
“birthday”:{
“from”:“1991-12-120”,
“to”:“2020-02-20”,
“include_lower”:true,
“include_upper”:false
}
}
}
}

wildcard查询

//可以使用通配符*和?
GET /lib/user/_search
{
“query”:{
“wildcard”:{“last_name”:“lao*”}
}
}

fuzzy 实现模糊查询

GET /lib/user/_search
{
“query”:{
“fuzzy”:{
“last_name”:“liaolii”
}
}
}
同样可以查询出last_name 值为laoli的数据

过滤查询

属性介绍:
must 必须满足
should 满足其中一个即可
must_not 不必满足

只查询满足的条件

  GET /lib5/user/_search
 {
   "query": {
     "bool": {
       "filter": {
         {
           "terms":{
            "name":"laowang"
           }
         }
       }
     }
   }
 }

bool过滤查询

满足年龄是25或者生日是2020-02-20,不必满足年龄是30

 GET /lib5/user/_search
 {
   "query": {
     "bool": {
       "should": [
          {"term":{"age":25}},
          {"term":{"birthdate":"2020-02-20"}}
        ],
        "must_not": {
          "term":{"age":30}
        }
     }
   }
 }

高亮搜索结果

GET /lib/user/_search
{
“query”:{
“match”:{
“last_name”:“laoli”
}
},
“highlight”:{
“fields”:{
“last_name”:{}
}
}
}
//会将要高亮显示的字段值用标签包裹

Bulk API 实现批量操作

批量添加

POST /lib2/emp/_bulk
{“index”:{"_id":1}}
{“name”:“xiaowang”,“age”:1}
{“index”:{"_id":2}}
{“name”:“xiaoli”,“age”:2}

//所有操作一起执行
POST /lib2/emp/_bulk
{“delete”:{"_index":“lib2”,"_type":“emp”,"_id":“2”}} --删除
{“create”:{"_index":“lib3”,"_type":“emp”,"_id":“100”}} --创建新的索引和类型并添加
{“name”:“wangwu”}
{“index”:{"_index":“lib3”,"_type":“emp”}} --添加,id由es服务器生成
{“name”:“zhaoliu”}
{“update”:{"_index":“lib2”,"_type":“emp”,"_id":“1”}} – 更新
{“doc”:{“age”:“50”}}
bulk会把要处理的数据载入到内存中,所以数量是有限制的,最佳的数量取决于硬件、文档的大小和复杂性,一般建议1000-5000个文档,大小建议5-15MB,默认不超过100M,可以再es的配置文件中进行配置

版本控制

es采用了乐观锁来保证数据的一致性,当用户对document进行操作时,需要制定操作的版本,版本号存在冲突时,es会提示冲突并跑异常(VersionConflictEngineException异常)。
内部版本控制使用的是 _version,取值范围 1 -2的63次方-1
外部版本控制:version和version_type=external 配合使用切versioin需要大于es中的version的值
PUT /lib/user/2/?version=4&version_type=external
{
“first_name”:“xiaoli”,
“last_name”:“laoli”,
“age”:55,
“about”:“I like to collect rockalbums”,
“interrests”:[“music”]
}

mapping

GET /lib/usr/_mapping 查看指定类型的mapping映射,默认由es服务器生成,es服务器会根据数据自动判断类型,简称动态映射。
GET /lib/user/_search?q=last_name:laoli

默认情况下,数值、日期不进行分词,只有text类型可以分词。
mapping的属性介绍:
index 是否分词
analyzer 指定分词器,默认standard analyzer
search_analyzer 指定搜索时的分词器,同analyzer 相同
ignore_above 文本超过指定值,将会忽略

//自定义mappingd
es默认会为每一个字段都建立倒排索引,如果不需要需要再mappings中添加index=false,这样该字段不会建立倒排索引,也不会被检索。
PUT /lib4
{
“settings”:{
“index”:{
“number_of_shards”: 3,
“number_of_replicas”: 0
}
},
“mappings”:{
“users”:{
“properties”:{
“name”:{“type”:“text”},
“username”:{“type”:“text”,“analyzer”:“standard”},
“carate_time”:{“type”:“date”,“index”:false},
“age”:{“type”:“integer”}
}
}
}
}

copy_to

//如果多个text类型的field都需要被索引,则在创建mapping的时候,可以将多个field拷贝到一个field,在索引的时候检索这一个字段就可以了,能够显著提升检索性能。

PUT /lib6/user
{
	"properties":{
		"name":{
			"type":"text",
			"copy_to":"fullcontents"
		},
		"address":{
			"type":"text",
			"copy_to":"fullcontents"
		}
	}
}

中文分词器的使用

ik带有两个分词器:ik_max_word,会将文本做最细粒度的拆分,尽可能的拆分出词语。ik_smart,会做最粗粒度的拆分,已被拆分的词语不会再次被其他词语占有

 PUT /lib5
 {
   "settings": {
     "number_of_shards": 3,
     "number_of_replicas": 0
   },
   "mappings": {
     "user":{
       "properties": {
         "name":{"type": "text","analyzer": "ik_max_word"},
         "address":{"type": "text","analyzer": "ik_max_word"},
         "age":{"type": "integer"},
         "interests":{"type": "text","analyzer": "ik_max_word"},
         "birthdat":{"type": "date"}
       }
     }
   }
 }

scroll大数据量查询

如果查询数据量较大,可以使用scroll查询,分批返回数据,达到滚动加载数据的效果,但是他和分页并不是同一个性质,这里要做好区分。


 GET /lib7/user/_search?scroll=1m   --指定每批查询时间最大为1分钟
 {
   "query": {
     "match_all": {}
   },
   "sort": ["_doc"],  -- 不按默认的相关度排序,提高性能
   "size":3  -- 每批次查询3条
 }
 //每次下旬结果会返回scroll_id,下次查询直接传递该值

 GET /_search/scroll
 {
   "scroll":"1m",
   "scroll_id":"DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAAABFmFwWWdERWwxUXJPWEN0SzIzS2duNkEAAAAAAAAAAhZhcFlnREVsMVFyT1hDdEsyM0tnbjZBAAAAAAAAAAMWYXBZZ0RFbDFRck9YQ3RLMjNLZ242QQ=="
 }
 

你可能感兴趣的:(ElasticSearch)