Elasticsearch学习笔记
安装部署
部署方式有两种
方法一:部署在本地
需要到官网下载安装包
Elasticsearch安装包
kibana可视化ui安装包
安装环境必须为jdk8以上否则无法运行
kibana安装需要修改在config文件下的kibana.yml文件
elasticsearch.hosts: localhost:9200
配置完成后便可运行启动文件
Elasticsearch启动发生进入文件bin目录下,运行elasticsearch.bat便可启动,第一次启动时间较并且会占用大量内存,建议本机运行内存为16g
运行成功界面
运行后访问9200端口
运行成功后便可以运行kibana,进入到bin目录下运行kibana.bat
,运行时间较长需要耐心等待
API
(1) 创建/全量替换
记录不存在就是创建, 否则是全量替换
PUT /index/type/id
{
"属性名" : "value"
...
}
(2) 创建/修改
创建
//如果不传id, 则系统自动生成一个UUID
POST /index/type/
{
"属性名":修改值
}
或者
POST /index/type/id
{
"属性名":修改值
}
修改
//没有带上的属性会被清除
POST /index/type/id
{
"属性名":修改值
}
//批量导入
POST /index/type/_bulk
{“index”:{"id":}}
{"属性名":}
(3) 查询
GET /index/type/id
//查询所有
GET /index/type/_search
(4) 删除
只是逻辑删除, 将其标记为delete, 当数据越来越多时, ES会自动物理删除.
DELETE /index/type/id
实例
(1) 新增
PUT /company/employee/1
{
"age":25,
"salary":"20k",
"skill":["java","mysql","es"]
}
//POST 命令新增数据时, 如果不传id, 则系统自动生成一个UUID.
POST /company/employee
{
"age":30,
"salary":"30k",
"skill":["python","redis","hadoop"]
}
批量生成
POST /company/employee/_bulk
{"index":{"_id":"1"}}
{
"age":30,
"salary":"30k",
"skill":["python","redis","hadoop"]
}
{"index":{"_id":"2"}}
{
"age":30,
"salary":"30k",
"skill":["python","redis","hadoop"]
}
{"index":{"_id":"3"}}
{
"age":30,
"salary":"30k",
"skill":["python","redis","hadoop"]
}
(2) 查询
GET /company/employee/1
(3) 修改
POST /company/employee/1
{
"age":40,
"salary":"100k"
}
//使用put也可以更新
```xml
PUT /company/employee/1
{
"age":18,
"salary":"50K",
"skill":["c++"]
}
PUT 是全量替换, 且是幂等操作. 上面的POST修改, skill属性被清除了, 属性现在只有age和salary
(4) 删除
DELETE /company/employee/1
Partial Update
部分更新.
(1) 语法
post /index/type/id/_update
{
"doc": {
"属性名" : "value"
...
}
}
(2) 与全量替换和普通修改的区别
在应用程序中, 全量替换是先从ES中查询出记录, 然后在修改, 一个属性都不能少. 而部分更新就不用先从ES查询记录了, 可以直接修改, 且不用所有属性都列出.
部分更新如果只包含部分属性, 那么其他没有被包含的属性仍然存在, 但普通修改其他没有被包含的属性就直接清除了.
(3) 实例
添加数据
PUT /company/employee/1
{
"age":25,
"salary":"20k",
"skill":["java","mysql","es"]
}
部分更新
POST /company/employee/1/_update
{
"doc": {
"age": 18,
"salary": "50K"
}
}
检索功能
(1) 搜索所有index数据.
GET /_search
(2) 搜索指定index, type下的数据(index和type可以有多个)
GET /index1/_search
GET /index1,index2/_search
GET /index1/type1/_search
GET /index1/type1,type2/_search
GET /index1,index2/type1,type2/_search
(3) 搜索所有index下的指定type的数据.
GET /_all/employee,product/_search
query string search
这个查询就类似于HTTP里的GET请求, 参数放在URL上.
(1) 语法
GET /index/type/_search?q=属性名:属性值
GET /index/type/_search?q=+属性名:属性值
GET /index/type/_search?q=-属性名:属性值
也可以省略属性名, 直接q=属性值
GET /index/type/_search?q=属性值
(2) + 和 - 的区别
默认是+, 指必须包含该字段, - 指不包含该字段.
(3) 实例
GET goods/_search?q=-brand:Apple
GET goods/_search?q=brand:Apple
GET goods/_search?q=Apple
(4) _all metadata的原理
GET /index/type/_search?q=属性值.
这个语句是从所有属性中搜索包含指定的关键字的数据. 那么ES在搜索时是遍历所有document中的每一个field吗? 不是的, 我们在插入一条document时, ES会自动将多个field的值, 全部用字符串的方式串联起来, 变成一个长的字符串(以空格作为分隔符),作为_all field的值,同时进行分词建立倒排索引. 如果在搜索时没有指定属性名, 就会默认搜索_all field. (生产环境不使用
query DSL
DSL, Domain Specified Language,特定领域的语言. 这个查询就类似于HTTP里的POST请求, 参数放在body中.
查询所有数据
GET bank/_search
{
"query": {
"match_all": {}
},
//排序
"sort": [
{
"_id": {
"order": "desc"
}
}
]
}
full-text search
全文搜索.
(1) 基础使用
GET /goods/_search
{
"query": {
"match": {
"name": "耳机"
}
}
}
搜索标题中至少包含first, second, third, fourth中三个单词的文章.
GET /website/article/_search
{
"query": {
"match": {
"title": {
"query": "first second third fourth",
"minimum_should_match": "75%"
}
}
}
}
(2) multi_match
multi_match 用于查询词匹配多个属性. 这里涉及到几种匹配策略:
best-fields
doc的某个属性匹配尽可能多的关键词, 那么这个doc会优先返回.
most-fields
某个关键词匹配doc尽可能多的属性, 那么这个doc会优先返回.
cross_fields
跨越多个field搜索一个关键词.
phrase search
(1) 短语搜索, 与全文搜索有什么区别呢?
全文搜索会将"查询词"拆解开来, 去倒排索引中一一匹配, 只要能匹配上任意一个拆解后的关键词, 就可以作为结果返回. 而短语搜索在全文搜索的基础上, 要求关键词必须相邻. (注意短语搜索的"查询词"也是会被分词的)
GET /book/_search
{
"query": {
"match": {
"abs": "思想家 主题 重要读物 故事"
}
}
}
GET /book/_search
{
"query": {
"match_phrase": {
"abs": "海登•怀特被誉为人类伟大的思想家之一"
}
}
}
//只有一条记录
(2) 原理:
短语搜索的原理实际上是相邻匹配(proximity match). Lucene建立的倒排索引结构为: 关键词 -> 文档号, 在文档中的位置, 在文档出现的频率等, 当一个"查询词"包含多个关键词时, Lucene先通过关键词找到对应的文档号, 判断多个关键词所在的文档号是否相同, 然后再判断在文档中的位置是否相邻.
(3) 实例
GET /book/_search
{
"query": {
"match_phrase": {
"abs": {
"query": "海登 人类",
"slop": 10
}
}
}
}
短语搜索默认是搜索相邻的关键词, 但也可以搜索间隔几个位置的关键词. 间隔越小相关度分数越高.
a. 从abs中搜索"海登 人类", 海登 和人类必须在同一个doc中, 且间隔不能超过10.
(4)优化短语搜索: rescore
短语搜索的性能要比全文搜索的性能低10倍以上, 所以一般我们要用短语搜索时都会配合全文搜索使用. 先通过全文搜索出匹配的doc, 然后对相关度分数最高的前n条doc进行rescore短语搜索. (这里只能用于分页搜索)
GET /book/_search
{
"query": {
"match": {
"abs": "海登 主题"
}
},
"rescore": {
"window_size": 1,
"query": {
"rescore_query": {
"match_phrase": {
"abs": {
"query": "海登 主题",
"slop": 10
}
}
}
}
}
}
(5) match_phrase_prefix
匹配短语的前缀, 用于做搜索推荐. 比如我们在百度输入一个关键词, 立马就会推荐一系列查询词, 这个就是搜索推荐.
GET /book/_search
{
"query": {
"match_phrase_prefix": {
"title": "且在人间"
}
}
}
term search
term查询, 是一种结构化查询, "查询词"不会被分词, 结果要么存在要么不存在, 不关心结果的score相关度. 如果查询text属性, 需要改为查询filed.keyword.
GET /book/_search
{
"query": {
"term": {
"title.keyword": {
"value": "叙事的虚构性"
}
}
}
(2) 常用语法
为了提高效率, term搜索一般与filter和constant_score联用. constant_score 以固定的评分来执行查询(默认为1), 而filter不计算score相关度, 因此执行效率非常高.
GET /book/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"title.keyword": "叙事的虚构性"
}
}
}
}
}
query filter
(1) 语法
query filter 用于过滤数据, 不参与score相关度计算, 效率很高. 适用于范围查询以及不计算相关度score的精确查询(filter + term)
(2) 实例
GET /book/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"date.keyword": "2019-3"
}
},
"boost": 1.3
}
}
}
搜索title中包含"叙事的虚构性"或"互联网算法"的帖子.
GET /book/_search
{
"query": {
"constant_score": {
"filter": {
"terms": {
"title.keyword": ["叙事的虚构性","互联网算法"]
}
}
}
}
}
搜索title中只包含"叙事的虚构性"的帖子.
如果想搜索title中只包含叙事的虚构性的帖子, 就需要新增一个字段tags_count, 表示tags中有几个tag, 否则就无法搜索.
聚合
聚合包括分组和统计, 其中分组操作包括term, histogram, date_histogram, filter. 统计操作包括count, avg, max, min, sum, cardinality, percentiles, percentile_ranks等.
注意: 聚合的属性不能被分词.
语法
GET /index/type/_search
{
size: 0,
"aggs": {
"NAME": {
"AGG_TYPE": {
"field": "field_name"
}
}
}
}
(2)统计哪种颜色的电视销量最高
GET /televisions/sales/_search
{
"size": 0,
"aggs": {
"max_sales_color": {
"terms": {
"field": "color.keyword"
}
}
}
}
统计每种颜色电视的平均价格
GET /televisions/sales/_search
{
"size": 0,
"aggs": {
"group_by_color": {
"terms": {
"field": "color.keyword"
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
统计每种颜色电视的平均价格, 以及统计每种颜色下每个品牌的平均价格.
这里就涉及到嵌套分组了, 也叫做多层下钻分析.
GET /televisions/sales/_search
{
"size": 0,
"aggs": {
"group_by_color": {
"terms": {
"field": "color.keyword"
},
"aggs": {
"color_avg_price": {
"avg": {
"field": "price"
}
},
"group_by_brand": {
"terms": {
"field": "brand.keyword"
},
"aggs": {
"brand_avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
}
}
mysql数据同步到es
使用es官方开源中间件logstash
1.下载对应es版本的logstash
官方地址
2.下载对应的mysql的jar包
3.将jar包放在/logstash-core/lib/路径下
input{
jdbc{
jdbc_driver_library => "E:\\logstash-7.4.2\\logstash-core\\lib\\jarsmysql-connector-java-8.0.19.jar"
jdbc_driver_class =>"com.mysql.cj.jdbc.Driver"
jdbc_connection_string => "jdbc:mysql://127.0.0.1:3306/shopping?characterEncoding=UTF-8&serverTimezone=GMT%2B8"
jdbc_user =>"root"
jdbc_password =>"root"
#刷新任务,默认为一分钟
schedule =>"* * * * *"
#清空上次last_value的数据
clean_run => true
statement =>"SELECT * FROM goods "
#satement => "select * from goods where update_time > :sql_last_value and update_time < now() order by update_time desc"
}
}
output{
elasticsearch {
hosts =>[ "47.95.109.143:9200"]
index =>"goods"
document_id =>"%{id}"
}
}
要求需要mysql表中是更新时间的字段和id字段
4.运行
在logstash的bin目录下运行命令 logstash -f …/config/mysql.conf