倒排索引:
id | name |
---|---|
1 | 北京布鞋 |
2 | 南京布鞋 |
3 | 澳洲皮鞋 |
正排索引的搜索是按照一条文档一条文档进行匹配查询(先查id再匹配判断)
根据以上的正排索引我们会生成按name分词的倒排索引
name | doc1 | doc2 | Doc3 |
---|---|---|---|
北京 | 1 | 0 | 0 |
南京 | 0 | 1 | 0 |
澳洲 | 0 | 0 | 1 |
布鞋 | 1 | 1 | 0 |
倒排索引是直接进行匹配判断,获取到文档ID后,根据文档ID再去查询正排索引获取数据
倒排索引在查询语句分析出后,才去确认创建那个filed的倒排索引
设置timeout时间,在超过这个时间之后会将这个时间段内查询到的数据返回,后续的还会查询但是不会返回,
所以在查询大量数据的是时候进来使用分片查询
from : 1 ,开始位置1
size : 100 , 查询100条
query 翻译是查询 , 会有相关度计算 (相关度算法后面回解释)
filter 翻译是过滤 , 只有结果没有相关度计算
命令
查询body
{
"query":{
"match":{
"name":"张三"
}
}
}
结果集分析
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.271394,
"hits" : [
{
"_index" : "user",
"_type" : "user",
"_id" : "2",
"_score" : 2.271394,
"_source" : {
"name" : "张三",
"age" : 21,
"desc" : "这是一个测试用户"
}
}
]
}
}
field | 描述 |
---|---|
took | 查询花费时间单位 毫秒 |
timed_out | 是否开启timeout |
_shards.total | 查询了多少shard |
_shards.successful | 成功的查询了多少shard |
_shards.failed | 多少个shard没有被查询到 |
hits.max_score | 最大相关度事多少 |
hits.hits | 查询结果(是经过封装过后的) |
hits.hits._index | 该数据的索引 |
hits.hits._type | 该数据的类型 |
hits.hits._score | 该数据的相关度 |
hits.hits._id | 该docment的ID |
hits.hits._source | 该docment的内容 |
命令与全文检索相同
查询body
{
"query":{
"macth_phrase":{
"name":"张三"
}
}
}
结果分析与全文检索一致
命令与全文检索一致
查询body
{
"query":{
"match": {
"name": "张"
}
},
"highlight": {
"fields": {
"name": {}
}
}
}
结果集分析
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.271394,
"hits" : [
{
"_index" : "user",
"_type" : "user",
"_id" : "2",
"_score" : 2.271394,
"_source" : {
"name" : "张三",
"age" : 21,
"desc" : "这是一个测试用户"
},
"highlight" : {
"name" : [
"张三"
]
}
}
]
}
}
field | 描述 |
---|---|
highlight | 标红字的field |
name | index的一个field 与 source中的name是一个意义 |
命令 同上
查询body 按name 进行分组
{
"aggs": {
"group_by_name": {
"terms": {
"field": "age"
}
}
}
}
结果分析
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "user",
"_type" : "user",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"name" : "张三",
"age" : 21,
"desc" : "这是一个测试用户"
}
},
{
"_index" : "user",
"_type" : "user",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"name" : "李四",
"age" : 80,
"desc" : "这是一个老人"
}
},
{
"_index" : "user",
"_type" : "user",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "测试用户1",
"age" : 23,
"desc" : "这是一个用户1"
}
}
]
},
"aggregations" : {
"group_by_name" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : 21,
"doc_count" : 1
},
{
"key" : 23,
"doc_count" : 1
},
{
"key" : 80,
"doc_count" : 1
}
]
}
}
}
feild | 描述 |
---|---|
aggregations.buckets.key | 分组值 |
aggregations.buckets.value | 分组计数 |
命令 同上
查询body
{
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
}
}
结果分析
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "user",
"_type" : "user",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"name" : "张三",
"age" : 21,
"desc" : "这是一个测试用户"
}
},
{
"_index" : "user",
"_type" : "user",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"name" : "李四",
"age" : 80,
"desc" : "这是一个老人"
}
},
{
"_index" : "user",
"_type" : "user",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "测试用户1",
"age" : 23,
"desc" : "这是一个用户1"
}
}
]
},
"aggregations" : {
"avg_age" : {
"value" : 41.333333333333336
}
}
}
field | 描述 |
---|---|
aggregations.avg_age | avg_age是我们查询的时候自定义的名称与body中的名称相对应 |
aggregations.avg_age.value | 针对于这个avg_age的平均值也就是所有用户的平均age |
命令同上
检索body
{
"query": {
"range": {
"age": {
"gte": 20,
"lte": 30
}
}
}
}
结果分析与全文检索一致
命令 GET /_mget
查询body
{
"docs":[
{
"_index":"user",
"_type":"user",
"_id":1
},
{
"_index":"test1",
"_type":"test1",
"_id":1
}
]
}
结果分析
{
"docs" : [
{
"_index" : "user",
"_type" : "user",
"_id" : "1",
"_version" : 5,
"_seq_no" : 6,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "测试用户111",
"age" : 23,
"desc" : "这是一个用户1111"
}
},
{
"_index" : "test1",
"_type" : "test1",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "test1"
}
}
]
}
多个index下的结果可以i 一起返回,节省io请求,优化方式之一
当我们使用一个字符串进行排序的时候,实际上是使用的field分词之后的单词进行排序的,而不是那字符串本身进行排序,我们需要将排序字段单独设置一个mapping index设置为false ,不索引,使用字段本身进行排序
我们在查询的时候会进行倒排索引的查询,在查询倒排索引的时候会将查询结果以二进制数组的方式作为缓存
例如我们上面的倒排索引, 查询南京就会出现[0,1,0]这样的数组,当下一个一模一样的查询过来时,不会再查询索引表,而是直接使用这个缓存
### 增删改路由
分词器就就是将一段话按词语进行切分,时态转换,单复数转换
es中按切分的词语创建了倒排索引的表
分词器的组成
elasticsearch的内置分词器
standard analyzer : 大小写转换 空格拆分 (默认)
simple analyzer : 简单分词器 空格下划线拆分
whitespace analyzer :
Language analyzer : 特定语言分词器
1. mapping是index的元数据,每个field都有自己的mapping,它决定了数据类型,建立索引的行为,还有搜索行为
2. mapping的基础类型
1. text
2. keyword 不会进行分词
3. integer
4. long
5. date 需要指定format格式
6. float
7. double
3. 不可修改,重点,重点,重点
命令 GET /index/_mapping/type
结果解析
{
"user" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"desc" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
},
"fielddata" : true
}
}
}
}
}
field | 描述 |
---|---|
user | index索引 |
mappings | 该索引下所有的field的mapping设置 |
properties | 属性集合 |
age/name | 我们的属性 |
type | field对应的类型 |
fields | 一个属性可以在属性内再次设置它的mapping |
fidlds.keyword | 属性的第二个mapping这是不是它的mapping而是name.keyword的mapping要使用这个mapping的时候查询条件是name.keyword不是name |
PUT /user
{
"mappings": {
"properties": {
"name":{
"type": "text",
"analyzer": "english"
}
}
}
}
PUT /user/_mapping
{
"properties":{
"name":{
"type":"text"
,
"fielddata":true
}
}
}
#### 水平扩容
将现有集群的内存扩大
增加节点加入集群,当每个节点上只有一个shard的时候就遇到了瓶颈,这时我们可以增加replica shard来再次增加性能
当机器增加或减少是集群会将已有的shard重新分配到现有机器上保持负载均衡,这是需要一个
在重新分配的时候需要一个机器来计算并调配资源所以集群中需要一个master节点
管理索引的元数据,默认情况下集群回自动选举一个master节点
master节点不会去承载请求(一般不会去承载数据)
当master节点宕机的时候集群状态是red
自动选举一个新的master
如果有primary shard丢失,会将丢失的primary shard 的replica shard 提升为primary shard
这是这个primary shard 无法在创建新的replica shard的时候集群是yellow状态
宕机的节点重启之后会rebalance,根据primaryshard进行数据恢复
es底层使用的是lucene,lucene底层index是分为多个segment,每个segment都会存储一部分数据,
buffer始终存在,不停的写入刷新到segment中,磁盘写入完成后清空buffer
buffer每次写满或refresh_interval之后都会将数据commint到一个新的index segment中去
删除会将数据记录在.del文件中,查询结果会去匹配这个文件,将删除的数据去掉,不会返回,当commint point 的时候将标记为deleted的数据从内存及磁盘上删除
refresh_interval:内存间隔多长时间数据会执行以上所有操作
refresh_interval默认设置是1s,在设置的时候需要加单位设置 1s,2ms,3min等
当translog文件到达一定大小时会将buffer中的数据新建一个segment,并进行commint point写入OS cache及磁盘上,同时记录那些segment提交过,translog日志文件清空,这个过程叫做flush
translog内记录的数据是包含没有fsync的segment中的数据的,OS cache中的数据也是依靠translog内的数据恢复的
flush触发机制30分钟或translog过大
commint point 的时候会将已有的segment merge成一个segment刷新到OS cache和磁盘上,并删除之前的segment这样会减少segment文件过多的问题
一个index下如果有多个type 那么docment_id就会冲突?
答:这时不可以使用数据的ID来设置,需要使用elasticsearch生成的ID否则方法id两个表中的某一条数据ID重复elasticsearch只会存储一条数据(不管是那个版本禁止一个index下有多个type)
Elasticsearch中每个shard上的数据最优大小是多少有算法吗?(未解决)
最后的问题我依旧没有解决,如果有了解的小伙伴记得私信一下我哦