windows中操作kibana,kibana与elasticsearch均为5.2.0版本

注意点:现在kibana/elasticsearch最新版本为7.0,与5.2.0的语法有出入,需要注意



语法,自己查询

kibana为操作elasticserch的界面,地址可以在启动日志中看到:


kibana的启动日志

界面展示:


kibana测试操作界面

一下为一些操作练习:

#写入

PUT /ecommerce/product/1

{

    "name" : "gaolujie yagao",

    "desc" :  "gaoxiao meibai",

    "price" :  30,

    "producer" :      "gaolujie producer",

    "tags": [ "meibai", "fangzhu" ]

}

#写入

PUT /ecommerce/product/2

{

    "name" : "jiajieshi yagao",

    "desc" :  "youxiao fangzhu",

    "price" :  25,

    "producer" :      "jiajieshi producer",

    "tags": [ "fangzhu" ]

}

#写入

PUT /ecommerce/product/3

{

    "name" : "zhonghua yagao",

    "desc" :  "caoben zhiwu",

    "price" :  40,

    "producer" :      "zhonghua producer",

    "tags": [ "qingxin" ]

}

#查询所有

GET /ecommerce/product/_search

{

  "query": {

    "match_all": {}

  }

}

#查询name中带有yagao的数据

GET /ecommerce/product/_search

{

  "query": {

    "match": {

      "name": "yagao"

    }

  }

}

#查询name为yagao并且按照price降序排序

GET /ecommerce/product/_search

{

  "query": {

    "match": {

      "name":"yagao"

    }

  },

    "sort":[

        {

          "price":"desc"

        }

      ]

}

#分页查询,只查询一条

GET /ecommerce/product/_search

{

  "query": {

    "match_all": {}

  },

  "from": 0,

  "size": 1

}

#只查询price与name

GET /ecommerce/product/_search

{

  "query":{

    "match_all": {}

  },

  "_source": ["price","name"]

}

# 查询name中匹配价格大于30牙膏

GET /ecommerce/product/_search

{

  "query": {

    "bool": {

      "must": [

        {"match": {

          "name": "yagao"

        }}

      ],

      "filter": {

        "range": {

          "price": {

            "gt": 30

          }

        }

      }

    }

  }

}

#全文检索

GET /ecommerce/product/_search

{

  "query": {

    "match": {

      "producer": "yagao producer"

    }

  }

}

#短语短语匹配

GET /ecommerce/product/_search

{

  "query": {

    "match_phrase": {

      "producer": "jiajieshi producer"

    }

  }

}

#高亮显示xianshi高亮显示显示producer

GET /ecommerce/product/_search

{

  "query": {

    "match": {

      "producer": "yagao producer"

    }

  },

  "highlight": {

    "fields": {

      "producer": {}

    }

  }

}

#将文本field的fielddata属性设置为true

PUT /ecommerce/_mapping/product

{

  "properties": {

    "tags": {

      "type": "text",

      "fielddata": true

    }

  }

}

#计算每个tag下的商品数量

GET /ecommerce/product/_search

{

  "size": 0,

  "aggs": {

    "group_by_tags": {

      "terms": {

        "field": "tags"

      }

    }

  }

}

#对名称中包含yagao的商品,计算每个tag下的商品数量

GET /ecommerce/product/_search

{

  "query": {

    "match": {

      "name": "yagao"

    }

  },

  "aggs": {

    "all_tags": {

      "terms": {

        "field": "tags"

      }

    }

  }

}

#先分组,再算每组的平均值,计算每个tag下的商品的平均价格

GET /ecommerce/product/_search

{

  "size": 0,

  "aggs": {

    "group_by_tags": {

      "terms": {

        "field": "tags"

      },

      "aggs": {

        "avg_price": {

          "avg": {

            "field": "price"

          }

        }

      }

    }

  }

}

#计算每个tag下的商品的平均价格,并且按照平均价格降序排序

GET /ecommerce/product/_search

{

  "size": 0,

  "aggs": {

    "group_by_tags": {

      "terms": {

        "field": "tags",

        "order": {

          "avg_price": "desc"

        },

        "size": 10

      },

      "aggs": {

        "avg_price": {

          "avg": {

            "field": "price"

          }

        }

      }


   }

  }

}


#按照指定的价格范围区间进行分组,然后在每组内再按照tag进行分组,最后再计算每组的平均价格

GET /ecommerce/product/_search

{

  "size": 0,

  "aggs": {

    "group_by_price": {

      "range": {

        "field": "price",

        "ranges": [

          {

            "from": 0,

            "to": 20

          },

          {

            "from": 20,

            "to": 40

          },

          {

            "from": 40,

            "to": 50

          }

        ]

      },

      "aggs": {

        "group_by_tags": {

          "terms": {

            "field": "tags"

          },

          "aggs": {

            "average_price": {

              "avg": {

                "field": "price"

              }

            }

          }

        }

      }

    }

  }

}

#es自动生成id,使用的是GUID的算法,可以避免同一时间,不同节点,同时创建索引id的时候造成id相同的情况,语法如下:

POST /test_index/my_test

{

  "test":"mytest2"

}

结果如下:


es自动创建索引id,长度为20个字符,URL安全,base64编码,GUID,分布式系统并行生成时不可能会发生冲突

#定制返回结果

_source元数据:就是说,我们在创建一个document的时候,使用的那个放在request body中的json串,默认情况下,在get的时候,会原封不动的给我们返回回来

PUT /test_index/my_test/1

{

  "test1":"test1",

  "test2":"test2"

}

GET /test_index/my_test/1?_source=test1

结果如下:


定制返回结果

#document的全量替换

1)    语法与创建文档是一样的,如果document id不存在,那么就创建;如果document id已经存在,那么就是全量替换操作,替换document的json串内容

2)    document是不可变的,如果要修改document的内容,第一种方式就是全量替换,直接对document重新建立索引,替换里面所有的内容

3)    es会将老的document标记为deleted,然后新增我们给定的一个document,当我们创建的越来越多的document的时候,es会在适当的实际在后台自动删除标记为deleted的document



#document的强制创建

1)    创建文档与圈梁替换的语法一样,有时我们只是想新建文档,不想替换文档,如果强制进行创建呢?

2)    PUT /index/type/id?op_type=create 或者 PUT /index/type/id/_create

最终结果:


最终强制创建失败

#document的删除

1)    DELETE /index/type/id

2)    不会理解为为例删除,只会将其标记为deleted,当数据越来越多的时候,在后台自动删除



#上机演练基于_version进行乐观锁的并发控制

开两个kibana客户端

PUT /test_index/my_test/7

{

  "test_str":"test001"

}


put的结果

PUT /test_index/my_test/7?version=1

{

  "test_str":"test002"

}


更新结果,同时带上数据的版本号,确保说,es中的数据的版本号,跟客户端中的数据的版本号是相同的,才能修改


另外一个客户端,尝试基于version=1的版本进行修改,同样带上version版本号,进行乐观锁的并发控制:

PUT /test_index/my_test/7?version=1

{

  "test_str":"test001"

}


version=1的更新,直接报错




#商机动手实战演练基于external version进行乐观锁并发控制

es提供了一个feature,就是说,你可以不用它提供的内部的_version版本号来进行并发控制,可以基于自己维护的一个版本号进行并发控制。举个例子,假如你的数据在mysql中也有一份,然后你的应用系统本身就维护了一个版本号,无论是什么自己生成的,程序控制的。这个时候,你进行乐观锁并发控制的时候,可能并不是想要用es内部的_version来进行控制,而是用你自己维护的那个version来进行控制。

原先的语法:url?version=1

现在的语法:url?version=1&version_type=external

version_type=external,唯一的区别在于,_version,只有当你提供的version与es中的_version一模一样的时候,才可以进行修改,只要不一样,就报错;当version_type=external的时候,只有当你提供的version比es中的_version大的时候,才能完成修改

es,_version=1,?version=1,才能更新成功

es,_version=1,?version>1&version_type=external,才能成功,比如说?version=2&version_type=external


#partial update实现原理、手动实践

1、什么是partial update?

PUT /index/type/id,创建文档&替换文档,就是一样的语法

一般对应到应用程序中,每次的执行流程基本是这样的:

(1)应用程序先发起一个get请求,获取到document,展示到前台界面,供用户查看和修改

(2)用户在前台界面修改数据,发送到后台

(3)后台代码,会将用户修改的数据在内存中进行执行,然后封装好修改后的全量数据

(4)然后发送PUT请求,到es中,进行全量替换

(5)es将老的document标记为deleted,然后重新创建一个新的document

partial update

post /index/type/id/_update

{

  "doc": {

      "要修改的少数几个field即可,不需要全量的数据"

  }

}

看起来,好像就比较方便了,每次就传递少数几个发生修改的field即可,不需要将全量的document数据发送过去

2、图解partial update实现原理以及其优点


partial update实现原理



#es,其实是有个内置的脚本支持的,可以基于groovy脚本实现各种各样的复杂操作

基于groovy脚本,如何执行partial update

```

PUT /test_index/test_type/11

{

  "num": 0,

  "tags": []

}

```

(1)内置脚本

```

POST /test_index/test_type/11/_update

{

  "script" : "ctx._source.num+=1"

}

{

  "_index": "test_index",

  "_type": "test_type",

  "_id": "11",

  "_version": 2,

  "found": true,

  "_source": {

    "num": 1,

    "tags": []

  }

}

```

(2)外部脚本

```

//注意,下面一行为脚本内容,脚本的存放位置为:


脚本存放位置

ctx._source.tags+=new_tag

POST /test_index/test_type/11/_update

{

  "script": {

    "lang": "groovy",

    "file": "test-add-tags",

    "params": {

      "new_tag": "tag1"

    }

  }

}

```

(3)用脚本删除文档

···

ctx.op = ctx._source.num == count ? 'delete' : 'none'

POST /test_index/test_type/11/_update

{

  "script": {

    "lang": "groovy",

    "file": "test-delete-document",

    "params": {

      "count": 1

    }

  }

}

···

(4)upsert操作,如果指定的document不存在,就执行upsert中的初始化操作;如果指定的document存在,就执行doc或者script指定的partial update操作

···

POST /test_index/test_type/11/_update

{

  "script" : "ctx._source.num+=1",

  "upsert": {

      "num": 0,

      "tags": []

  }

}

···

#mget批量查询

```

GET /test_index/_mget

{

  "docs":[

    {

      "_type":"my_test",

      "_id":"1"

    },

    {

      "_type":"my_test",

      "_id":"2"

    }

    ]

}

//结果:

{

  "docs": [

    {

      "_index": "test_index",

      "_type": "my_test",

      "_id": "1",

      "_version": 2,

      "found": true,

      "_source": {

        "test3": "test3"

      }

    },

    {

      "_index": "test_index",

      "_type": "my_test",

      "_id": "2",

      "found": false

    }

  ]

}

```

#如果查询的document是一个index下的不同type种的话

···

GET /test_index/_mget

{

  "docs":[

      {

        "_type":"my_test",

        "_id":"1"

      },

      {

        "_type":"other_test",

        "_id":"1"

      }


    ]

}

···

//结果

···

{

  "docs": [

    {

      "_index": "test_index",

      "_type": "my_test",

      "_id": "1",

      "_version": 2,

      "found": true,

      "_source": {

        "test3": "test3"

      }

    },

    {

      "_index": "test_index",

      "_type": "other_test",

      "_id": "1",

      "_version": 1,

      "found": true,

      "_source": {

        "name": "li ming",

        "age": 12

      }

    }

  ]

}

···

#如果查询的数据都在同一个index下的同一个type下,最简单了

···

GET /test_index/_mget

{

  "ids":["1","2"]

}

//结果

{

  "docs": [

    {

      "_index": "test_index",

      "_type": "other_test",

      "_id": "1",

      "_version": 1,

      "found": true,

      "_source": {

        "name": "li ming",

        "age": 12

      }

    },

    {

      "_index": "test_index",

      "_type": null,

      "_id": "2",

      "found": false

    }

  ]

}

···

mget的重要性:

可以说mget是很重要的,一般来说,在进行查询的时候,如果一次性要查询多条数据的话,那么一定要用batch批量操作的api尽可能减少网络开销次数,可能可以将性能提升数倍,甚至数十倍,非常非常之重要


#批量增删改

有哪些类型的操作可以执行呢?

(1)delete:删除一个文档,只要1个json串就可以了

(2)create:PUT /index/type/id/_create,强制创建

(3)index:普通的put操作,可以是创建文档,也可以是全量替换文档

(4)update:执行的partial update操作

bulk api对json的语法,有严格的要求,每个json串不能换行,只能放一行,同时一个json串和一个json串之间,必须有一个换行,否则就会出现下面的效果:


按照清晰的json格式来写会报错的

1、bulk语法

```

POST /_bulk

{ "delete": { "_index": "test_index", "_type": "test_type", "_id": "3" }}

{ "create": { "_index": "test_index", "_type": "test_type", "_id": "12" }}

{ "test_field":    "test12" }

{ "index":  { "_index": "test_index", "_type": "test_type", "_id": "2" }}

{ "test_field":    "replaced test2" }

{ "update": { "_index": "test_index", "_type": "test_type", "_id": "1", "_retry_on_conflict" : 3} }

{ "doc" : {"test_field2" : "bulk test1"} }

//结果

{

  "took": 41,

  "errors": true,

  "items": [

    {

      "delete": {

        "found": true,

        "_index": "test_index",

        "_type": "test_type",

        "_id": "10",

        "_version": 3,

        "result": "deleted",

        "_shards": {

          "total": 2,

          "successful": 1,

          "failed": 0

        },

        "status": 200

      }

    },

    {

      "create": {

        "_index": "test_index",

        "_type": "test_type",

        "_id": "3",

        "_version": 1,

        "result": "created",

        "_shards": {

          "total": 2,

          "successful": 1,

          "failed": 0

        },

        "created": true,

        "status": 201

      }

    },

    {

      "create": {

        "_index": "test_index",

        "_type": "test_type",

        "_id": "2",

        "status": 409,

        "error": {

          "type": "version_conflict_engine_exception",

          "reason": "[test_type][2]: version conflict, document already exists (current version [1])",

          "index_uuid": "6m0G7yx7R1KECWWGnfH1sw",

          "shard": "2",

          "index": "test_index"

        }

      }

    },

    {

      "index": {

        "_index": "test_index",

        "_type": "test_type",

        "_id": "4",

        "_version": 1,

        "result": "created",

        "_shards": {

          "total": 2,

          "successful": 1,

          "failed": 0

        },

        "created": true,

        "status": 201

      }

    },

    {

      "index": {

        "_index": "test_index",

        "_type": "test_type",

        "_id": "2",

        "_version": 2,

        "result": "updated",

        "_shards": {

          "total": 2,

          "successful": 1,

          "failed": 0

        },

        "created": false,

        "status": 200

      }

    },

    {

      "update": {

        "_index": "test_index",

        "_type": "test_type",

        "_id": "1",

        "_version": 3,

        "result": "updated",

        "_shards": {

          "total": 2,

          "successful": 1,

          "failed": 0

        },

        "status": 200

      }

    }

  ]

}

bulk操作中,任意一个操作失败,是不会影响其他的操作的,但是在返回结果里,会告诉你异常日志

```

2、bulk size最佳大小

bulk request会加载到内存里,如果太大的话,性能反而会下降,因此需要反复尝试一个最佳的bulk size。一般从1000~5000条数据开始,尝试逐渐增加。另外,如果看大小的话,最好是在5~15MB之间。

===================

#es路由原理

(1)document路由到shard上是什么意思?

(2)路由算法:shard = hash(routing) % number_of_primary_shards

举个例子,一个index有3个primary shard,P0,P1,P2

每次增删改查一个document的时候,都会带过来一个routing number,默认就是这个document的_id(可能是手动指定,也可能是自动生成)

routing = _id,假设_id=1

会将这个routing值,传入一个hash函数中,产出一个routing值的hash值,hash(routing) = 21

然后将hash函数产出的值对这个index的primary shard的数量求余数,21 % 3 = 0

就决定了,这个document就放在P0上。

决定一个document在哪个shard上,最重要的一个值就是routing值,默认是_id,也可以手动指定,相同的routing值,每次过来,从hash函数中,产出的hash值一定是相同的

无论hash值是几,无论是什么数字,对number_of_primary_shards求余数,结果一定是在0~number_of_primary_shards-1之间这个范围内的。0,1,2。

(3)_id or custom routing value

默认的routing就是_id

也可以在发送请求的时候,手动指定一个routing value,比如说put /index/type/id?routing=user_id

手动指定routing value是很有用的,可以保证说,某一类document一定被路由到一个shard上去,那么在后续进行应用级别的负载均衡,以及提升批量读取的性能的时候,是很有帮助的

(4)primary shard数量不可变的谜底


es路由原理图

#一致性原理以及quorum机制深入理解

(1)consistency,one(primary shard),all(all shard),quorum(default)

我们在发送任何一个增删改操作的时候,比如说put /index/type/id,都可以带上一个consistency参数,指明我们想要的写一致性是什么?

put /index/type/id?consistency=quorum

one:要求我们这个写操作,只要有一个primary shard是active活跃可用的,就可以执行

all:要求我们这个写操作,必须所有的primary shard和replica shard都是活跃的,才可以执行这个写操作

quorum:默认的值,要求所有的shard中,必须是大部分的shard都是活跃的,可用的,才可以执行这个写操作

(2)quorum机制,写之前必须确保大多数shard都可用,int( (primary + number_of_replicas) / 2 ) + 1,当number_of_replicas>1时才生效

quroum = int( (primary + number_of_replicas) / 2 ) + 1

举个例子,3个primary shard,number_of_replicas=1,总共有3 + 3 * 1 = 6个shard

quorum = int( (3 + 1) / 2 ) + 1 = 3

所以,要求6个shard中至少有3个shard是active状态的,才可以执行这个写操作

(3)如果节点数少于quorum数量,可能导致quorum不齐全,进而导致无法执行任何写操作

3个primary shard,replica=1,要求至少3个shard是active,3个shard按照之前学习的shard&replica机制,必须在不同的节点上,如果说只有2台机器的话,是不是有可能出现说,3个shard都没法分配齐全,此时就可能会出现写操作无法执行的情况

es提供了一种特殊的处理场景,就是说当number_of_replicas>1时才生效,因为假如说,你就一个primary shard,replica=1,此时就2个shard

(1 + 1 / 2) + 1 = 2,要求必须有2个shard是活跃的,但是可能就1个node,此时就1个shard是活跃的,如果你不特殊处理的话,导致我们的单节点集群就无法工作

(4)quorum不齐全时,wait,默认1分钟,timeout,100,30s

等待期间,期望活跃的shard数量可以增加,最后实在不行,就会timeout

我们其实可以在写操作的时候,加一个timeout参数,比如说put /index/type/id?timeout=30,这个就是说自己去设定quorum不齐全的时候,es的timeout时长,可以缩短,也可以增长



#document query的内部原理

1、客户端发送请求到任意一个node,成为coordinate node

2、coordinate node对document进行路由,将请求转发到对应的node,此时会使用round-robin随机轮询算法,在primary shard以及其所有replica中随机选择一个,让读请求负载均衡

3、接收请求的node返回document给coordinate node

4、coordinate node返回document给客户端

5、特殊情况:document如果还在建立索引过程中,可能只有primary shard有,任何一个replica shard都没有,此时可能会导致无法读取到document,但是document完成索引建立之后,primary shard和replica shard就都有了


query的内部原理

#bulk api奇特的json格式

{"action": {"meta"}}\n

{"data"}\n

{"action": {"meta"}}\n

{"data"}\n

[{

  "action": {

  },

  "data": {

  }

}]

1、bulk中的每个操作都可能要转发到不同的node的shard去执行

2、如果采用比较良好的json数组格式

允许任意的换行,整个可读性非常棒,读起来很爽,es拿到那种标准格式的json串以后,要按照下述流程去进行处理

(1)将json数组解析为JSONArray对象,这个时候,整个数据,就会在内存中出现一份一模一样的拷贝,一份数据是json文本,一份数据是JSONArray对象

(2)解析json数组里的每个json,对每个请求中的document进行路由

(3)为路由到同一个shard上的多个请求,创建一个请求数组

(4)将这个请求数组序列化

(5)将序列化后的请求数组发送到对应的节点上去

3、耗费更多内存,更多的jvm gc开销

我们之前提到过bulk size最佳大小的那个问题,一般建议说在几千条那样,然后大小在10MB左右,所以说,可怕的事情来了。假设说现在100个bulk请求发送到了一个节点上去,然后每个请求是10MB,100个请求,就是1000MB = 1GB,然后每个请求的json都copy一份为jsonarray对象,此时内存中的占用就会翻倍,就会占用2GB的内存,甚至还不止。因为弄成jsonarray之后,还可能会多搞一些其他的数据结构,2GB+的内存占用。

占用更多的内存可能就会积压其他请求的内存使用量,比如说最重要的搜索请求,分析请求,等等,此时就可能会导致其他请求的性能急速下降

另外的话,占用内存更多,就会导致java虚拟机的垃圾回收次数更多,跟频繁,每次要回收的垃圾对象更多,耗费的时间更多,导致es的java虚拟机停止工作线程的时间更多

4、现在的奇特格式

{"action": {"meta"}}\n

{"data"}\n

{"action": {"meta"}}\n

{"data"}\n

(1)不用将其转换为json对象,不会出现内存中的相同数据的拷贝,直接按照换行符切割json

(2)对每两个一组的json,读取meta,进行document路由

(3)直接将对应的json发送到node上去

5、最大的优势在于,不需要将json数组解析为一个JSONArray对象,形成一份大数据的拷贝,浪费内存空间,尽可能地保证性能

#timeout机制详解

1、我们如果发出一个搜索请求的话,会拿到一堆搜索结果,本节课,我们来讲解一下,这个搜索结果里的各种数据,都代表了什么含义

2、我们来讲解一下,搜索的timeout机制,底层的原理,画图讲解

GET /_search

{

  "took": 6,

  "timed_out": false,

  "_shards": {

    "total": 6,

    "successful": 6,

    "failed": 0

  },

  "hits": {

    "total": 10,

    "max_score": 1,

    "hits": [

      {

        "_index": ".kibana",

        "_type": "config",

        "_id": "5.2.0",

        "_score": 1,

        "_source": {

          "buildNum": 14695

        }

      }

    ]

  }

}

took:整个搜索请求花费了多少毫秒

hits.total:本次搜索,返回了几条结果

hits.max_score:本次搜索的所有结果中,最大的相关度分数是多少,每一条document对于search的相关度,越相关,_score分数越大,排位越靠前

hits.hits:默认查询前10条数据,完整数据,_score降序排序

shards:shards fail的条件(primary和replica全部挂掉),不影响其他shard。默认情况下来说,一个搜索请求,会打到一个index的所有primary shard上去,当然了,每个primary shard都可能会有一个或多个replic shard,所以请求也可以到primary shard的其中一个replica shard上去。

timeout:默认无timeout,latency平衡completeness,手动指定timeout,timeout查询执行机制

timeout=10ms,timeout=1s,timeout=1m

GET /_search?timeout=10m


timeout详解

#multi-index和multi-type搜索模式

告诉你如何一次性搜索多个index和多个type下的数据

/_search:所有索引,所有type下的所有数据都搜索出来

/index1/_search:指定一个index,搜索其下所有type的数据

/index1,index2/_search:同时搜索两个index下的数据

/*1,*2/_search:按照通配符去匹配多个索引

/index1/type1/_search:搜索一个index下指定的type的数据

/index1/type1,type2/_search:可以搜索一个index下多个type的数据

/index1,index2/type1,type2/_search:搜索多个index下的多个type的数据

/_all/type1,type2/_search:_all,可以代表搜索所有index下的指定type的数据

#初识搜索引擎_分页搜索以及deep paging性能问题深度图解揭秘

1、讲解如何使用es进行分页搜索的语法

size,from

GET /_search?size=10

GET /_search?size=10&from=0

GET /_search?size=10&from=20

2、什么是deep paging问题?为什么会产生这个问题,它的底层原理是什么?

deep paging性能问题,以及原理深度图解揭秘,很高级的知识点


deep paging

# _all metadata的原理和作用

GET /test_index/test_type/_search?q=test

直接可以搜索所有的field,任意一个field包含指定的关键字就可以搜索出来。我们在进行中搜索的时候,难道是对document中的每一个field都进行一次搜索吗?不是的

es中的_all元数据,在建立索引的时候,我们插入一条document,它里面包含了多个field,此时,es会自动将多个field的值,全部用字符串的方式串联起来,变成一个长的字符串,作为_all field的值,同时建立索引

后面如果在搜索的时候,没有对某个field指定搜索,就默认搜索_all field,其中是包含了所有field的值的

举个例子

{

  "name": "jack",

  "age": 26,

  "email": "jack@sina.com",

  "address": "guamgzhou"

}

"jack 26 jack@sina.com guangzhou",作为这一条document的_all field的值,同时进行分词后建立对应的倒排索引


#查看es自动建立的mapping,带出什么是mapping的知识点

GET /ecmmerce/_mapping/product


部分结果

自动或手动为index中的type建立的一种数据结构和相关配置,简称为mapping

dynamic mapping,自动为我们建立index,创建type,以及type对应的mapping,mapping中包含了每个field对应的数据类型,以及如何分词等设置

#两种搜索方式:

1、exact value

2017-01-01,exact value,搜索的时候,必须输入2017-01-01,才能搜索出来

如果你输入一个01,是搜索不出来的

2、full text

(1)缩写 vs. 全程:cn vs. china

(2)格式转化:like liked likes

(3)大小写:Tom vs tom

(4)同义词:like vs love

2017-01-01,2017 01 01,搜索2017,或者01,都可以搜索出来

china,搜索cn,也可以将china搜索出来

likes,搜索like,也可以将likes搜索出来

Tom,搜索tom,也可以将Tom搜索出来

like,搜索love,同义词,也可以将like搜索出来

就不是说单纯的只是匹配完整的一个值,而是可以对值进行拆分词语后(分词)进行匹配,也可以通过缩写、时态、大小写、同义词等进行匹配

1、什么是分词器

切分词语,normalization(提升recall召回率)

给你一段句子,然后将这段句子拆分成一个一个的单个的单词,同时对每个单词进行normalization(时态转换,单复数转换),分瓷器

recall,召回率:搜索的时候,增加能够搜索到的结果的数量

character filter:在一段文本进行分词之前,先进行预处理,比如说最常见的就是,过滤html标签(<span>hello<span> --> hello),& --> and(I&you --> I and you)

tokenizer:分词,hello you and me --> hello, you, and, me

token filter:lowercase,stop word,synonymom,dogs --> dog,liked --> like,Tom --> tom,a/the/an --> 干掉,mother --> mom,small --> little

一个分词器,很重要,将一段文本进行各种处理,最后处理好的结果才会拿去建立倒排索引

2、内置分词器的介绍

Set the shape to semi-transparent by calling set_trans(5)

standard analyzer:set, the, shape, to, semi, transparent, by, calling, set_trans, 5(默认的是standard)

simple analyzer:set, the, shape, to, semi, transparent, by, calling, set, trans

whitespace analyzer:Set, the, shape, to, semi-transparent, by, calling, set_trans(5)

language analyzer(特定的语言的分词器,比如说,english,英语分词器):set, shape, semi, transpar, call, set_tran, 5


1、如何建立索引

analyzed

not_analyzed

no

2、修改mapping

只能创建index时手动建立mapping,或者新增field mapping,但是不能update field mapping

PUT /website

{

  "mappings": {

    "article": {

      "properties": {

        "author_id": {

          "type": "long"

        },

        "title": {

          "type": "text",

          "analyzer": "english"

        },

        "content": {

          "type": "text"

        },

        "post_date": {

          "type": "date"

        },

        "publisher_id": {

          "type": "text",

          "index": "not_analyzed"

        }

      }

    }

  }

}

update mapping的时候会报错的

PUT /website

{

  "mappings": {

    "article":{

      "properties": {

        "author_id":{

          "type": "text"

        }

      }

    }

  }

}


update mapping报错

新增不报错

PUT /website/_mapping/article

{

  "properties": {

    "new_field":{

      "type": "text",

      "index":"not_analyzed"

    }

  }

}

##    filter与query对比大解密

filter,仅仅只是按照搜索条件过滤出需要的数据而已,不计算任何相关度分数,对相关度没有任何影响

query,会去计算每个document相对于搜索条件的相关度,并按照相关度进行排序

一般来说,如果你是在进行搜索,需要将最匹配搜索条件的数据先返回,那么用query;如果你只是要根据一些条件筛选出一部分数据,不关注其排序,那么用filter

除非是你的这些搜索条件,你希望越符合这些搜索条件的document越排在前面返回,那么这些搜索条件要放在query中;如果你不希望一些搜索条件来影响你的document排序,那么就放在filter中即可

3、filter与query性能

filter,不需要计算相关度分数,不需要按照相关度分数进行排序,同时还有内置的自动cache最常使用filter的数据

query,相反,要计算相关度分数,按照分数进行排序,而且无法cache结果


1、query phase

(1)搜索请求发送到某一个coordinate node,构构建一个priority queue,长度以paging操作from和size为准,默认为10

(2)coordinate node将请求转发到所有shard,每个shard本地搜索,并构建一个本地的priority queue

(3)各个shard将自己的priority queue返回给coordinate node,并构建一个全局的priority queue

2、replica shard如何提升搜索吞吐量

一次请求要打到所有shard的一个replica/primary上去,如果每个shard都有多个replica,那么同时并发过来的搜索请求可以同时打到其他的replica上去

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

推荐阅读更多精彩内容