ES 与SOLR
1.Solr在查询固定数据时,速度相对ES更快一些,但是数据如果是实时改变的,Solr的查询速度会降低很多,Es的查询的效率基本没有变化
2.Solr搭建基于需要依赖 Zookeeper来帮助管理,ES本身就支持集群的搭建,不需要第三方的介入
3.最开始Solr的社区可以说是非常火爆,针对国内的文档井不是很多,在ES出现之后,ES的社区火爆程度, 直线上升,Es的文档非常健全
4.ES对现在云计算和大数据支持的特别好
倒排序
将存放的数据,以一定的方式进行分词,并且将分词的内容存放到一个单独的分词库中
当用户去查询数据时,会将用户的查询关键字进行分词
然后去分词库中匹配内容,最终得到数据的d标识
根据d标识去存放数据的位置拉取到指定的数据
安装
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.2-linux-x86_64.tar.gz #下载tar -zxvf elasticsearch-7.6.2-linux-x86_64.tar.gz #解压cd elasticsearch-7.6.2bin/elasticsearch
配置
elasticsearch.yml
配置项 | 备注 |
---|---|
node.name | 节点名称 打开 |
network.host | 监听ip,打开 0.0.0.0 |
discovery.seed_hosts | 初始服务器ip “127.0.0.1” |
cluster.initial_master_nodes | 主节点 打开 |
cluster.name | 集群组名称 |
jvm.options
项目 | 说明 |
---|---|
-Xms256m | 初始内存大小 |
-Xmx256m | 最大内存大小 |
报错解决
- 错误:Exception in thread “main” java.lang.RuntimeException: don’t run elasticsearch as root.
原因:我们在使用elasticsearch的时候,如果是以root权限来执行elasticsearch则会报错,这是出于系统安全考虑设置的条件。由于ElasticSearch可以接收用户输入的脚本并且执行,为了系统安全考虑,
建议创建一个单独的用户用来运行ElasticSearch
解决:
groupadd elsearch #创建elsearch用户组及elsearch用户useradd elsearch -g elsearch -p elasticsearch #创建elsearch用户chown -R elsearch:elsearch elasticsearch-7.6.2 #更改elasticsearch文件夹及内部文件的所属用户及组为elsearch:elsearchsu elsearch #切换账户cd elasticsearch-7.6.2/bin #进入你的elasticsearch目录下的bin目录./elasticsearch -d #启动ps aux|grep elasticsearch #查看是否正常运行
- 错误:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
原因:elasticsearch用户拥有的内存权限太小,至少需要262144;
解决:切换到root用户,执行命令:
sysctl -w vm.max_map_count=262144 #查看结果:sysctl -a|grep vm.max_map_count #显示:vm.max_map_count = 262144 #上述方法修改之后,如果重启虚拟机将失效,所以:解决办法:在 /etc/sysctl.conf文件最后添加一行vm.max_map_count=262144即可永久修改
ES与mysql对应关系
mysql | ES |
---|---|
数据库 | Index |
表 | type (6以后已经作废) |
一行记录 | Document |
列 | Field |
Schema约束 | mapping |
索引 | |
SQL语句 | Query DSL |
Select * from table | GET http://… |
update table set … | PUT http://… |
Mapping映射
创建索引时预定义字段类型和相关属性,让索引更完善,提高查询效率
ES常用字段类型
常用类型 | ES中type类型 | 备注 |
---|---|---|
string,varchar,text | text keyword | 5.x以后不再支持string text类型:当一个字段是要被全文搜索的,比如Email内容、产品描述,应该使用text类型。设置text类型以后,字段内容会被分析,在生成倒排索引以前,字符串会被分析器分成一个一个词项。text类型的字段不用于排序,很少用于聚合。 keyword类型适用于索引结构化的字段,比如email地址、主机名、状态码和标签。如果字段需要进行过滤(比如查找已发布博客中status属性为published的文章)、排序、聚合。keyword类型的字段只能通过精确值搜索到。 |
integer | byte short integer long | |
float,double | float double half_float scaled_float | 32位单精度IEEE 754浮点类型 64位双精度IEEE 754浮点类型 16位半精度IEEE 754浮点类型 缩放类型的的浮点数 |
boolean | boolean | true和false |
date/datetime | date | 1. 日期格式的字符串,比如 “2018-01-13” 或 “2018-01-13 12:10:30” 2. long类型的毫秒数( milliseconds-since-the-epoch,epoch就是指UNIX诞生的UTC时间1970年1月1日0时0分0秒) 3. integer的秒数(seconds-since-the-epoch) |
bytes/binary | binary | 进制字段是指用base64来表示索引中存储的二进制数据,可用来存储二进制形式的数据,例如图像。默认情况下,该类型的字段只存储不索引。二进制类型只支持index_name属性。 |
array | array | 1. 字符数组: [ “one”, “two” ] 2. 整数数组: productid:[ 1, 2 ] 3. 对象(文档)数组: “user”:[ { “name”: “Mary”, “age”: 12 }, { “name”: “John”, “age”: 10 }], 注意:elasticSearch不支持元素为多个数据类型:[ 10, “some string” ] |
object | JSON对象,文档会包含嵌套的对象 | |
ip | ip类型的字段用于存储IPv4或者IPv6的地址 |
Mapping 支持属性
属性 | 描述 | 适用字段类型 |
---|---|---|
store | 是否单独设置此字段的是否存储而从_source字段中分离,只能搜索,不能获取值 “store”: false(默认)true | all |
index | 是否构建倒排索引(即是否分词,设置false,字段将不会被索引) “index”: true(缺省)false | string |
null_value | 设置一些缺失字段的初始化,只有string可以使用,分词字段的null值也会被分词 “null_value”: “NULL” | string |
boost | 检索时,字段级优先权重,默认值是1.0 “boost”: 1.23 | all |
search_analyzer | 设置搜索时的分词器,默认跟analyzer是一致的,比如index时用standard+ngram,搜索时用standard用来完成自动提示功能 “search_analyzer”: “ik” | text |
analyzer | 指定分词器,默认分词器为standard analyzer “analyzer”: “ik” | text |
include_in_all | all | |
index_name | all | |
norms | 是否归一化相关参数、如果字段仅用于过滤和聚合分析、可关闭 分词字段默认配置,不分词字段:默认{“enable”: false},存储长度因子和索引时boost,建议对需要参加评分字段使用,会额外增加内存消耗 “norms”: {“enable”: true, “loading”: “lazy”} | all |
更多参考https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-params.html
PUT /store { "mappings":{ "properties":{ "title":{ "type":"keyword" }, "price":{ "type":"integer" } } }}
中文分词
下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases
安装插件:把插件包 elasticsearch-analysis-ik(需要mvn编译过)解压到 elasticsearch\plugins\ik目录下,后启动ES 自动识别
测试分词
POST _analyze{ "analyzer": "ik_smart", "text": "我是一个程序员"}
创建mapping 分词只能用于text类型
PUT /store { "mappings":{ "properties":{ "title":{ "type":"text", "analyzer":"ik_max_word", "search_analyzer":"ik_max_word" }, "price":{ "type":"integer" } } }}
使用方法
访问方式
http://ip:9200/index/type/[id] #api格式curl -H "ContentType:application/json" -X PUT 127.0.0.1:9200/index -d '{ "settings":{ "number_of_shards":1, "number_of_replicas":0 }}'#命令行格式PUT /index{ "settings":{ "number_of_shards":1, "number_of_replicas":0 }}
查看健康状态
curl -X GET 127.0.0.1:9200/_cat/health?v
查询当前es集群中所有的indices
curl -X GET 127.0.0.1:9200/_cat/indices?v
创建初始化索引
PUT /store { "settings":{ "number_of_shards":1, //分片数量 "number_of_replicas":0 //备份数量 }, "mappings":{ "properties":{ "title":{ "type":"text", "analyzer":"ik_max_word" }, "price":{ "type":"integer" } } }}#blocks.read_only:true //只读#blocks.read:true //禁止读#blocks.write:true //禁止写#blocks.metadata:true //禁止操作metadata
向已有索引中添加新字段
POST /store/_mappings{ "properties":{ "status":{ "type":"integer" } } }
不支持删除或更新某个字段
获取索引配置
GET /store/_settings //获取配置GET /index1,index2/_settings //获取2个索引配置GET /_all/_settings //获取所有配置
删除记录
DELETE /store 索引DELETE /index/_doc/id 记录
删除条件记录
据term, match等查询方式去删除大量的文档 GET /store/_search替换成POST /store/_doc/_delete_by_query
Ps:如果需要删除的内容,是index下的大部分数据,推荐创建一个全新的index,将保留的文档内容,添加到全新的索引
POST /store/_doc/_delete_by_query{ query:条件}
插入记录
使用POST时不指定id, 会自动生成uuid,不方便更新删除,不推荐
POST /store/_doc{ "title": "php", "price": 20, "create_time": "2016-06-06"}
也可以使用PUT方法,但是需要传入id
PUT /store/_doc/4 { "title": "php", "price": 20, "create_time": "2016-06-06"}
获取记录
GET /store/_doc/idGET /store/_doc/id?_source=title //查询指定字段
更新记录指定字段
POST /store/_update/id{ "doc":{ "price":10 }}或PUT /store/_doc/id{ "price":50}
更新覆盖整条记录
POST /store/_doc/id{ "title": "php", "price": 20, "create_time": "2016-06-06"}
批量获取
GET /_mget{ "docs":[ { "_index" : "store", "_type" : "book", "_id" : 3 "_source":"price" //可指定字段,多个用数组形式 [] }, { "_index" : "store", "_type" : "book", "_id" : 4 } ]}//获取同一个索引同一个type下不同idGET /store/_mget{ "ids":["3","4"]}
Bulk批量CURD
行为 | 备注 |
---|---|
create | 文档不存在时创建 |
index | 创建新文档或替换已有文档 |
update | 局部更新 |
delete | 删除文档 |
{action:{metadata}}\n{requestbody}\n
批量新增加
POST /store/_bulk{"index":{"_id":1}}{"title":"php是世界上最好的语言","price":30}{"index":{"_id":2}}{"title":"java是世界上最难的语言","price":20}{"index":{"_id":3}}{"title":"python是人工智能语言","price":35}
批量删除
POST /store/_bulk{"delete":{"_id":1}}
批量更新
POST /store/_bulk{"update":{"_id":2}}{"doc":{"price":12}}
版本控制
版本控制用于乐观锁,内部版本控制:(version已被7淘汰,7使用if_seq_no 和 if_primary_term)
PUT /store/_doc/1?if_seq_no=0&if_primary_term=1{ "price":50}
版本控制用于乐观锁,外部版本控制,更新时外部版本号不得小于内部版本号:
PUT /store/_doc/1?version=4&version_type=external{ "price":50}
检索查询
Elasticsearch的检索语法比较特别,使用GET方法携带JSON格式的查询条件。
全检索:
curl -X GET 127.0.0.1:9200/store/_doc/_search
按条件检索:
_search: 查询
query:查询条件
bool:聚合查询组合条件 相当于()
must:必须满足 相当于and =
should:条件可以满足 相当于or
must_not:条件不需要满足,相当于and not
range:范围
gt: 大于
lt:小于
gte:大等于
lte:小等于
filter:条件过滤
term:不分词
普通查询
分页查询相当于limit
from和size 之合不能超过10000
GET /store/_search{ "from":0, "size":10}
使用term查询
term查询不会对指定关键词进行分词,而是从分词库中匹配
相当于 where title =”java”
GET /store/_search{ "query":{ "term":{ "title":"java" } }}
使用terms查询查询多个值
相当于 where title in (“php”,”java”)
GET /store/_search{ "query":{ "terms": { "title":["php","java"] } } }
match高级查询
match查询属于高层查询,他会根据你查询的字段类型不一样,采用不同的查询方式。
查询的是日期或者是数值的话,他会将你基于的字符串查询内容转换为日期或者数值对待。
如果查询的内容是一个不能被分词的内容( keyword), match查询不会对你指定的查询关键字进行分词
如果查询的内容时一个可以被分词的内容(text), match会将你指定的查询内容根据一定的方式去分词,去分词库中匹配指定的内容。
match查询,实际底层就是多个term查询,将多个term查询的结果给你封装到了一起
默认查询10条记录
GET /store/_search{ "query":{ "match": { "title":"php" } } }
match_all查询,返回所有数据,不指定查询条件
GET /store/_search{ "query":{ "match_all": {} } }
match_phrase查询,短语查询,slop定义关键词之间间隔多少未知单词 用逗号或空格间隔多个关键词
GET /store/_search{ "query":{ "match_phrase": { "title":{ "query":"p,p", "slop":2 } } } }
布尔match 基于一个字段,采用and或or的条件查询 用逗号或空格间隔多个关键词
GET /store/_search{ "query":{ "match": { "title":{ "query":"php java python", "operator":"or" } } } }
multi_match查询基于多个字段查询一个关键词
GET /store/_search{ "query":{ "multi_match": { "query":"php", "fields":["title"] } } }
其他查询
查询效率较低
perfix 前缀查询
类似 like “key%”
GET /store/_search{ "query":{ "prefix": { "title":"php" } } }
fuzzy相似查询
具有容错性
GET /store/_search{ "query":{ "fuzzy": { "title":{ "value":"php", "prefix_length":3 //可选,前三个不允许错 } } } }
wildcard查询
通配符 ? 或 *,?占一个字符
GET /store/_search{ "query":{ "wildcard": { "title":{ "value":"p??" } } } }
range查询
范围查询只针对数值 where (price>=20 and price <30) 符号 gt,gte,lt,lte
GET /store/_search{ "query":{ "range": { "price":{ "gte":20, "lt":30 } } } }
regexp正则查询
GET /store/_search{ "query":{ "regexp": { "title":"[a-p]h.*?" } } }
深分页scroll
ES对from+size是有限制的,from和size二者之和不能超过1W
from+size ES查询数据的方式:
- 第一步现将用户指定的关键进行分词
- 第二步将词汇去分词库中进行检索,得到多个文档的id
- 第三步去各个分片中去拉取指定的数据,耗时较长
- 第四步将数据根据 score进行排序
- 第五步根据from的值,将查询到的数据舍弃一部分
- 第六步返回结果
scroll查询数据方式
第一步现将用户指定的关键进行分词
第二步将词汇去分词库中进行检索,得到多个文档的id
第三步将文档的d存放在一个Es的上下文中
第四步根据你指定的size的个数去Es中检索指定个数的数据,拿完数据的文档id,会从上下文中移
第五步如果需要下一页数据,直接去ES的上下文中,找后续内容
Scroll查询方式,不适合做实时的查询
GET /store/_search?scroll=1m{ "query":{ "match_all": { } }, "size":2, "sort":[{ "price":{ "order":"desc" } }]}
查询结果中的 scroll_id 是内存上下文id, 用id查询下一页
GET /_search/scroll{ "scroll_id":"", "scroll":"1m"}
删除scroll
DELETE /_search/scroll/FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFERCUjRxM1VCS3gxSGNZVURIWWRJAAAAAAAAC5sWUmprMWhGYUpSNUd2X25paTg2RVROdw==
组合查询
bool查询
复合过滤器,将你的多个查询条件,以一定的逻辑组合在一起
must:所有的条件,用mus组合在一起,表示and true的意思
must not:将 must not中的条件,全部都不能匹配,标识and not true的意思
should:所有的条件,用 should组合在一起,表示or true的意思
例如 select * from store where (price=20 or price =30) and create_time <>”2016-06-06”
{ "query":{ "bool": { "should":[ {"term":{"price":20}}, {"term":{"price":30}} ], "must_not":{ "term":{"create_time":"2016-06-06"} } }, } }
boosting 查询
boosting查询可以帮助我们去影响查询后的 score
- positive:只有匹配上 positive的意询的内容,才会被放到返回的结果集中
- negative:如果匹配上和 positive并且也匹配上了 negative,就可以降低这样的文档 score
- negative boost:指定系数,必须小于1.0 系数会乘上score 降低排名
关于查询时,分数是如何计算的
- 搜索的关键字在文档中出现的频次越高,分数就越高
- 指定的文档内容越短,分数就越高
- 我们在搜索时,指定的关键字也会被分词,这个被分词的内容,被分词库匹配的个数越多,分数越高
GET /store/_search{ "query":{ "boosting":{ "positive":{ "match": { "title": "java" } }, "negative": { "match": { "title": "y" } }, "negative_boost": 0.2 } }}
filter查询
query,根据你的查询条件,去计算文档的匹配度得到一个分数,并且根据分数进行排序,不会做缓存的
filter,根据你的查询条件去查询文档,不去计算分数,而且filter会对经常被过滤的数据进行缓存
GET /store/_search{ "query":{ "bool":{ "filter":[ { "term":{ "title":"java" } }, { "term":{ "price":20 } } ] } }}
高亮查询
高亮查询就是你用户输入的关键字,以一定的特殊样式展示给用户,让用户知道为什么这个结果被检索出来
高亮展示的数据,本身就是文档中的一个Feld,单独将 FieldlAhighlight的形式返回给你
ES提供了一个 highlight属性,和 query同级别的
fields:指定哪些字段按高亮返回
fragment_size:指定高亮数据展示多少个字符回来
- pre_tags:指定前缀标签
- post_tags:指定后缀标签
GET /store/_search{ "query":{ "term":{ "title":"java" } }, "highlight":{ "fields":{ "title":{} }, "pre_tags":"<font color=red>", "post_tags":"</font>", "fragment_size":4 }}
聚合查询
ES的聚合查询和MYSQL的聚合查询类型,ES的聚合查询相比Mysql要强大的多,ES提供的统计数据的方式多种多样
GET /store/_search{ "aggs":{ "agg":{ //名字 ”agg_type":{ "" //属性:值 } } }}
去重计数查询
GET /store/_search{ "aggs":{ "agg":{ //名字 "cardinality":{ "field":"price" } } }}
范围统计
统计一定范围内出现的文档个数,比如,针对某一个Feld的值在0-100,100-200, 200-300之间文档出现的个数分别是多少
范围统计可以针对普通的数值,针对时间类型,针对类型都可以做相应的统计.
range , data_range, ip_range
GET /store/_search{ "aggs":{ "agg":{ "range":{ "field": "price", "ranges": [ {"from": 10,"to":50} ] } }}
统计聚合
他可以帮你查询指定Fed的最大值,最小值,平均值,平方和,,,
GET /store/_search{ "aggs":{ "agg":{ "extended_stats":{ "field": "price" } } }}
更多apihttps://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics.html
地图检索
geo_distance: 直线距离检索方式
geo_bounding_box: 以两个点确定一个矩形,获取在矩形内的全部数据
geo_polygon: 以多个点(至少3个点),确定一个多边形,获取多边形内的全部数据
GET /map/_search{ "query":{ "geo_distance":{ "location":{ "lon": 123.51551, //经度 "lat": 421.215, //纬度 }, "distance":2000, // 距离米 "distance_type":"arc" //圆形范围 } }}
GET /map/_search{ "query":{ "geo_bounding_box":{ "location":{ "top_left": { "lon": 123.51551, //经度 "lat": 421.215, //纬度 }, "bottom_right":{ "lon": 123.51551, //经度 "lat": 421.215, //纬度 } } } }}
GET /map/_search{ "query":{ "geo_polygon":{ "location":{ "points": [ { "lon": 123.51551, //经度 "lat": 421.215, //纬度 }, { "lon": 123.51551, //经度 "lat": 421.215, //纬度 }, { "lon": 123.51551, //经度 "lat": 421.215, //纬度 } ]} } }}
杀死进程
killps -ef|grep Elasticsearch | grep -v grep|awk '{print $2}'
Kibana
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.6.2-linux-x86_64.tar.gz
配置
配置项 | 备注 |
---|---|
elasticsearch.hosts: [“http://127.0.0.1:9200“] | es地址 |