1、索引(ElasticSearch)包多个分片
2、字段类型(映射)mapping )字段类型映射(字段是整型,还是字符型…)
3、文档(documents)
4、分片(Lucene索引,倒排索引)
elasticsearch是面向文档,关系型数据库和elasticsearch客观的对比!一切都是json!
elasticsearch(集群)中可以包含多个索引(数据库) ,每个索引中可以包含多个类型(表) ,每个类型下又包含多个文档(行) ,每个文档中又包含多个字段(列)。
Relational DB | Elasticsearch |
---|---|
数据库(database) | 索引(indices) |
表(tables) | types |
行(rows) | documents |
字段(columns) | fields |
物理设计:
elasticsearch在后台把每个索引划分成多个分片。每个分片可以在集群中的不同服务器间迁移
一个人就是一个集群! ,即启动的ElasticSearch服务,默认就是一个集群,且默认集群名为elasticsearch
逻辑设计:
一个索引类型中,包含多个文档,比如说文档1,文档2。当我们索引一篇文档时,可以通过这样的一个顺序找到它:索引->类型->文档id,通过这个组合我们就能索引到某个具体的文档。注意:ID不必是整数,实际上它是一个字符串。
索引是映射类型的容器, elasticsearch中的索引是一个非常大的文档集合。索|存储了映射类型的字段和其他设置。然后它们被存储到了各个分片上了。我们来研究下分片是如何工作的。使用elasticsearch-head-master新建索引。
一种type就像一类表,比如user表,order表。
注意:
ES5.X中一个index可以有多种type
ES6.X中一个index只能有一种type
ES7.X以后已经移除type这个概念
Mapping定义了每个字段的类型等信息,相当于关系数据库中的表结构
一个document相当于关系型数据库中的一行记录。
集群由一个或多个节点组成,一个集群有一个默认名称”elaticsearch”
集群的节点,一台机器或者一个进程
分片:是ES中所有数据文件块,也就是数据的最小单元块,ES中所有数据均衡的存储在集群中各个节点的分片中,会影响ES的性能、安全和稳定性, 所以很有必要了解一下它。单台机器无法存储大量数据,es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储。有了shard就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能
副本:一个服务器随时可能故障或宕机,此时shard可能就会丢失,因此可以为每个shard创建多个replica副本。replica可以在shard故障时提供备用服务,保证数据不丢失,多个replica还可以提升搜索操作的吞吐量和性能。
副本是分片的副本,分片有主分片(primary Shard)和副分片(replica Shard)之分
一个index数据在物理上被分布在多个主分片中,每个主分片只存放部分数据。
每个主分片可以有多个副本,叫副本分片,是主分片的复制
一个集群至少有一 个节点,而一个节点就是一-个elasricsearch进程 ,节点可以有多个索引默认的,如果你创建索引,那么索引将会有个5个分片( primary shard ,又称主分片)构成的,每一个主分片会有-一个副本( replica shard ,又称复制分片)
上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同-个节点内,这样有利于某个节点挂掉了,数据也不至于丢失。实际上, 一个分片是- -个Lucene索引, 一个包含倒排索引的文件目录,倒排索引的结构使得elasticsearch在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。
elasticsearch使用的是一种称为倒排索引 |的结构,采用Lucene倒排索作为底层。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。 例如,现在有两个文档,每个文档包含如下内容:
Study every day, good good up to forever # 文档1包含的内容
To forever study every day,good good up # 文档2包含的内容
为了创建倒排索引,我们首先要将每个文档拆分成独立的词(或称为词条或者tokens) ,然后创建一一个包含所有不重 复的词条的排序列表,然后列出每个词条出现在哪个文档:
现在,我们试图搜索 to forever,只需要查看包含每个词条的文档
两个文档都匹配,但是第一个文档比第二个匹配程度更高。如果没有别的条件,现在,这两个包含关键字的文档都将返回。
如果要搜索含有python标签的文章,那相对于查找所有原始数据而言,查找倒排索引后的数据将会快的多。只需要查看标签这一栏,然后获取相关的文章ID即可。完全过滤掉无关的所有数据,提高效率!
接下来的一切操作都在kibana中Dev Tools下的Console里完成。基础操作!
上一篇博客已经写了如何安装(https://blog.csdn.net/weixin_43190854/article/details/120493666?spm=1001.2014.3001.5501),现在来学学 如何使用。
IK分词器 中文分词器
分词:即把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一一个匹配操作,默认的中文分词是将每个字看成一个词(不使用用IK分词器的情况下),比如“我爱中国”会被分为”我”,”爱”,”中”,”国” ,这显然是不符合要求的,所以我们需要安装中文分词器ik来解决这个问题。
IK提供了两个分词算法: (ik_smart和ik_max_word ),其中ik_smart为最少切分,ik_max_word为最细粒度划分!
standard:默认分词器,按词切分,小写处理
输入 超级喜欢张艺兴java
发现张艺兴这个名字被拆分开了
这种自己需要的词,需要自己加到我们的分词器的字典中!
ik 分词器增加自己的配置
添加自定义的词添加到扩展字典中
elasticsearch目录/plugins/ik/config/IKAnalyzer.cfg.xml
创建 wangjiale.dic 字典文件,添加字典内容
以后的话,我们需要自己配置分词就在自己定义的dic文件进行配置即可!
一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
method | url地址 | 描述 |
---|---|---|
PUT(创建,修改) | localhost:9200/索引名称/类型名称/文档id | 创建文档(指定文档id) |
POST(创建) | localhost:9200/索引名称/类型名称 | 创建文档(随机文档id) |
POST(修改) | localhost:9200/索引名称/类型名称/文档id/_update | 修改文档 |
DELETE(删除) | localhost:9200/索引名称/类型名称/文档id | 删除文档 |
GET(查询) | localhost:9200/索引名称/类型名称/文档id | 查询文档通过文档ID |
POST(查询) | localhost:9200/索引名称/类型名称/文档id/_search | 查询所有数据 |
1、创建一个索引,添加数据
PUT /test1/type1/doc_1
{
"name":"zhangsan",
"age" : 9,
"tag" :["唱歌","技术宅","温暖"]
}
字符串类型:text、keyword
text:支持分词,全文检索,支持模糊、精确查询,不支持聚合,排序操作;
text类型的最大支持的字符长度无限制,适合大字段存储;
keyword:不进行分词,直接索引、支持模糊、支持精确匹配,支持聚合、排序操作。
keyword类型的最大支持的长度为——32766个UTF-8类型的字符,可以通过设置ignore_above指定自持字符长度,超过给定长度后的数据将不被索引,无法通过term精确匹配检索返回结果。
数值型:long、Integer、short、byte、double、float、half float、scaled float
日期类型:date
布尔类型:boolean
二进制类型:binary
等等…
3、指定字段的类型(使用PUT)
创建规则 类似于建库(建立索引和字段对应类型),也可看做规则的建立
PUT /test1/type1/doc_2
{
"mappings" : {
"properties" : {
"name" :{
"type" : "text"
},
"age" :{
"type" : "long"
},
"birth" : {
"type" : "date"
}
}
}
}
GET test1/type1/doc_2
扩展:通过命令 elasticsearch索引情况!通过get _cat/ 可以获取ElasticSearch的当前的很多信息!
GET _cat/indices?v
两种方案
方案一:旧的(使用put覆盖原来的值) 版本+1(_version)
但是如果漏掉某个字段没有写,那么更新是没有写的字段 ,会消失
PUT /test1/type1/doc_3
{
"name" :"doc_3",
"age" : 3,
"sex" : "女"
}
PUT /test1/type1/doc_3
{
"name" :"doc_3",
"age" : 4,
"sex" : "男"
}
第一次更新之后的数据,更新了age和sex字段,name字段没更新,但是还是在put中写入,此时没有丢失字段
第二次更新操作,更新了age字段,没有再写入name字段,此时name字段丢失
PUT /test1/type1/doc_3
{
"age" : 5,
"sex" : "男"
}
方案二:新的(使用post的update)
需要注意doc
不会丢失字段
PUT /test1/type1/doc_5
{
"name" :"doc_5",
"age" : 5,
"sex" : "男"
}
POST /test1/type1/doc_5/_update
{
"doc" :{
"name" :"xxxxx"
}
}
POST /test1/type1/doc_5/_update
{
"doc" :{
"dec" : "第一次更新操作将name更新了;现在是第二次更新操作,添加这一个desc字段"
}
}
通过DELETE 命令实现删除,根据你的请求来判断是删除索引还是删除文档记录!
DELETE /test1/type1/doc_5
使用RESTFUL 风格是我们ES推荐大家使用的!
1、添加数据
给文档doc_1,doc_2,doc_3添加数据
PUT /test/user/doc_1
{
"name": "张三",
"age": 23,
"desc": "一顿操作猛如虎,一看工资2500",
"tags": ["运动","阳光","直男"]
}
PUT /test/user/doc_2
{
"name": "张三",
"age": 40,
"desc": "法外狂徒",
"tags": ["运动","旅游","渣男"]
}
PUT /test/user/doc_3
{
"name": "李四",
"age": 30,
"desc": "mmp,不知道 如何形容",
"tags": ["靓仔","旅游","唱歌"]
}
GET test/user/doc_1
PUT /test/user/doc_3
{
"name": "李四22222",
"age": 30,
"desc": "今天天气真好,第一次更新操作,李四22222和desc",
"tags": ["靓仔","旅游","唱歌"]
}
4、Post _update,推荐使用这种更新方式!
POST /test/user/doc_1/_update
{
"doc" : {
"name" : "张三1"
}
}
GET test/user/doc_1
简单的条件查询,可以根据默认的映射规则,产生基本的查询!
GET /test/user/_search?q=name:张三
6、复杂操作搜索 select(排序,分页,高亮,模糊查询,精准查询)
搜索过滤
GET /test/user/_search
{
"query": {
"match": {
"name": "张三"
}
},
"_source": ["name","age"]
}
GET /test/user/_search
{
"query": {
"match": {
"name": "张三"
}
},
"_source": ["name","age"],
"sort": [
{
"age": {
"order": "asc"
}
}
]
}
GET /test/user/_search
{
"query": {
"match": {
"name": "张三"
}
},
"_source": ["name","age"],
"sort": [
{
"age": {
"order": "asc"
}
}
],
"from": 0,
"size": 10
}
布尔值查询
must(and),所有的条件都要符合 where id=1 and name = xxx
GET /test/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "张三"}
},
{
"match": {
"age": 40}
}
]
}
}
}
should(or),所有的条件都要符合 where id=1 or name = xxx
GET /test/user/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "李四"}
},
{
"match": {
"age": 40}
}
]
}
}
}
GET /test/user/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"name": "李四"
}
},
{
"match": {
"age": 40}
}
]
}
}
}
range范围
gt 大于
gte 大于等于
lte 小于
lte 小于等于
GET /test/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "张三"
}
}
],
"filter": {
"range": {
"age": {
"gte": 23 ,
"lte": 40
}
}
}
}
}
}
GET /test/user/_search
{
"query": {
"match": {
"tags": "旅游 阳光"
}
},
"_source": ["tags" ,"name"]
}
term查询是直接通过倒排索引指定的词条进程精确查找的
关于分词
term,直接查询精确的
match,会使用分词器解析!(先分析文档,然后通过分析的文档进行查询)
PUT /test/_doc/1
{
"name" : "鹿晗关晓彤在一起name",
"desc" : "鹿晗关晓彤在一起desc"
}
GET _analyze
{
"analyzer": "keyword",
"text": "鹿晗关晓彤在一起name"
}
GET _analyze
{
"analyzer": "standard",
"text": "鹿晗关晓彤在一起name"
}
GET test/_search
{
"query": {
"term": {
"name.keyword": {
"value": "张三"
}
}
}
}
多个值匹配精确查询
GET test/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"name.keyword": {
"value": "张三"
}
}
},{
"term": {
"age": {
"value": 23
}
}
}
]
}
}
}
默认高亮样式
GET test/_search
{
"query": {
"match": {
"name": "张三"
}
},
"highlight": {
"fields": {
"name": {
}
}
}
}
GET test/_search
{
"query": {
"match": {
"name": "张三"
}
},
"highlight": {
"pre_tags": " "
,
"post_tags": "",
"fields": {
"name": {
}
}
}
}