Elasticsearch的使用

Elasticsearch的使用

1、介绍

Elasticsearch是一个(近乎)实时的分布式搜索和分析引擎。它可以帮助你用前所未有的速度去处理大规模数据, 它不但稳定、可靠、快速,而且也具有良好的水平扩展能力,是专门为分布式环境设计的,它可以用于全文搜索,结构化搜索以及分析,当然你也可以将这三者进行组合。Elasticsearch是一个建立在全文搜索引擎 Apache Lucene 基础上的搜索引擎,可以说Lucene是当今最先进,最高效的全功能开源搜索引擎框架.
下载地址

2、特性

ElasticSearch是基于Lucene开发的分布式搜索框架,包含如下特性:

  1. 分布式索引、搜索。
  2. 索引自动分片、负载均衡。
  3. 自动发现机器、组建集群。
  4. 支持Restful 风格接口。
  5. 配置简单等。
  6. 海量数据的存储。

3、Elasticsearch对应结构

Es对数据的存储采用是:
Index(索引)------Mysql(Table)
Document(文档)-------Mysql(Table中一行数据)
选择索引(Es7.0后 ,彻底遗弃type,只有索引和文档),存储的数据就叫文档
一个索引只存储一种类型的数据

4、安装

基于Docker安装Elasticsearch

#1.创建并运行容器
docker run -d --name es9200 -e "discovery.type=single-node" -p 9200:9200 elasticsearch:7.12.1
#2.访问测试
#云服务器:开放安全组:9200
#http://ip地址:9200/

启动成功后测试访问图片如下
在这里插入图片描述

如果出现启动失败:
max virtual monery xxxx [65530] is to low
这个错误意思:当前默认可用内存太小了,需要设置的大一点
在服务器上执行下面的命令:

vim /etc/sysctl.conf
#输入:
vm.max_map_count=655300
#重新加载
sysctl -p
#重新启动容器:
docker start es9200

基于docker安装kibana

kibana:是一个免费且开放的用户界面,能够让对 Elasticsearch
数据进行可视化,还可以进行各种操作,跟踪查询负载,到理解请求如何流经整个应用,都能轻松完成。
ELK:标准化日志平台E:Elasticsearch 作为日志存储和分析框架,L:Logstash
作为日志采集框架,获取日志存储到Es,K:Kibana 可视化网站,可以通过网页操作ES 目前的日志服务推荐:云解决方案:
阿里云-日志服务(SLS) 行业领先的日志大数据解决方案,一站式提供数据收集、清洗、分析、可视化和告警功能。
全面提升海量日志处理能力,实时挖掘数据价值,智能助力研发/运维/运营/安全等场景

1.查询es的地址:::::或者当出现看可视化界面出现key找不到也可看看ip是否真确或者相对应的版本

docker inspect es9200

如下图
在这里插入图片描述

2.创建并运行容器

docker run -d --name kibana5601 -p 5601:5601 kibana:7.1.1

3.修改配置文件

docker exec -it kibana5601 bash
vi config/kibana.yml
  1. 更改es的地址
    在这里插入图片描述
    重启
docker restart kibana5601 

5、测试
访问测试
开放端口号:5601
http://ip地址:5601/

5、Kibana可视化操作ES

1.查看索引管理器

在这里插入图片描述

Elasticsearch:
Index Managenment 实现Es的索引管理

在这里插入图片描述

Kibana:
Index Patterns 实现基于Kibana可视化的索引信息

在这里插入图片描述

2.为索引设置可视化
设置可视化之后,就可以通过Kibana进行可视化的操作
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.基于Kibana实现可视化操作
在这里插入图片描述
RestfulApi操作Es
在这里插入图片描述

6、常用的Restful API:(text和keyword区别)

text和keyword的区别就是keyword不可区分 也可以 name.keyword来使用 但是要设置索引的时候设置

#创建索引
PUT /es211
#删除索引
DELETE /es211
#创建索引
PUT /es211-lx
#设置索引的Mapping格式,定义文档格式
PUT /es211-lx/_mapping
{
  "properties": {
    "_class": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
    "id": {
        "type": "long"
    },
    "name":{
      "type":"text"
    },
    "sex":{
      "type":"text"
    },
    "ctime":{
      "type":"date"
    }
  }
}

#新增文档
POST /es211-lx/_doc/1
{
  "id":1,
  "name":"帅帅",
  "sex":"男人",
  "ctime":"2020-05-11"
}
POST /es211-lx/_doc/2
{
  "id":2,
  "name":"琪琪",
  "sex":"女人",
  "ctime":"2020-05-11"
}
#修改文档
PUT /es211-lx/_doc/2
{
  "id":2,
  "name":"琪琪",
  "sex":"女生",
  "ctime":"2020-05-11"
}
#查询单个文档
GET /es211-lx/_doc/2
#删除文档
DELETE /es211-lx/_doc/2

7、springboot操作es (Spring Data Elasticsearch)

添加依赖

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2.实现配置
application.yml配置 连接es服务器

spring:
  elasticsearch:
    rest:
      uris: ip地址:9200

3.编写代码 三层

@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "es2008")//标记对应的索引名称
public class Student {
    private Integer id;
    private String name;
    private String sex;//性别
}
public interface StudentDao extends ElasticsearchRepository<Student,Integer> {
}
public interface StudentService {
    String save(Student student);
    Iterable<Student> all();
}
@Service
public class StudentServiceImpl implements StudentService{
    @Autowired
    private StudentDao dao;
    @Override
    public String save(Student student) {
        if(dao.save(student)!=null){
            return "新增成功";
        }else {
            return "新增失败";
        }
    }

    @Override
    public Iterable<Student> all() {
        return dao.findAll();
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = EsApplication.class)
public class EsTest {
    @Autowired
    private StudentService studentService;

    @Test
    public void t1(){
        Student student=new Student(1,"小王");
        System.err.println(studentService.save(student));
    }
    @Test
    public void t2(){
        studentService.all().forEach((s)-> System.err.println(s));
    }
}

8、es批处理

基于es实现批量的操作,比如批量新增、批量修改、批量删除
核心代码:

//1.实例化客户端对象 连接服务器
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(new HttpHost("39.105.189.141",
                        9200, "http")));
        //Es可以实现批量操作,方便快速进行同步数据
        BulkRequest request=new BulkRequest();
        //批量新增
        for(int i=101;i<1000;i++){
            //DeleteRequest
            //UpdateRequest
            //IndexRequest
            
            request.add(new IndexRequest("es2008").id(i+"").source(
                    JSON.toJSONString(new Student(i,"批量-"+i,"man")),XContentType.JSON));
        }
        //执行批处理
        BulkResponse responses=client.bulk(request,RequestOptions.DEFAULT);
        System.err.println(responses.status().toString());
        //3.关闭
        client.close();

9、各种查询

TermQueryBuilder:词条查询
词条查询是ElasticSearch的一个简单查询。它仅匹配在给定字段中含有该词条的文档,而且是确切的、未经分析的词条。term查询会查找我们设定的准确值。term查询本身很简单,它接受一个字段名和我们希望查找的值.MatchQueryBuilder(MatchQueryBuilder输入的词条会被es解析并进行分词,在此过程中就已经转换成全小写)查询效果一样
命令模式:

POST es2008/_search
{
  "from": 0,     
  "size": 5,	 
  "query": {
    "term": {
      "name": {
        "value": "批量-101"
      }
    }
  }
}

代码:

TermQueryBuilder termQuery=QueryBuilders.termQuery("sex","man");

TermsQueryBuilder:
词条查询(Term Query)允许匹配单个未经分析的词条,多词条查询(Terms Query)可以用来匹配多个这样的词条。只要指定字段包含任一我们给定的词条,就可以查询到该文档。


RangeQueryBuilder:
范围查询,比如数字类型、日期类型等的范围查询:gt gte lt lte
在这里插入图片描述

 RangeQueryBuilder rangeQuery=QueryBuilders.rangeQuery("id");
        rangeQuery.lt(200).gte(122);

WildcardQueryBuilder:
通配符查询,?匹配单个字符,*匹配多个字符,请注意,此查询可能会很慢,因为它需要遍历许多项。

 //3.通配符查询  *任意个字符  ?单个字符
        WildcardQueryBuilder wildcardQuery=QueryBuilders.wildcardQuery("name","*8");

FuzzyQueryBuilder:
模糊查询,可以使用%进行模糊,还可以指定前缀字符模糊匹配
对于中文的模糊搜索,应该先安装中文分词,比如IK分词器
我爱北京天安门
我 我爱 北京 我爱北京 天安门 北京天安门 爱北京天安门

 //5.模糊查询 % super supzr
        FuzzyQueryBuilder fuzzyQuery=QueryBuilders.fuzzyQuery("name","批量-232");
        fuzzyQuery.prefixLength(4);//设置固定前缀匹配

BoolQueryBuilder:
布尔查询,拼接多个查询条件
常见的拼接关系:
must:必须 同时满足 类似 and
must_not:必须不 不能满足
should:应该 只有有一个满足即可 类似 or
filter:过滤 就是must替代品 只能进行数据筛选,进行额外操作

//6.布尔查询 拼接查询条件
        BoolQueryBuilder boolQuery=QueryBuilders.boolQuery();
//        boolQuery.should();
//        boolQuery.mustNot();
//        boolQuery.filter();
        boolQuery.must(termQuery).must(rangeQuery);

9、1 上述的查询 (//范围查询中有获取实体类的写法)
@SpringBootTest
public class EsTest {
    @Autowired
    private ElasticsearchRestTemplate restTemplate;

    //范围查询
    @Test
    public void t1(){
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
        .withQuery(QueryBuilders.rangeQuery("money").from(300).to(3000)).build();
        List<SearchHit<Worker>> workers=restTemplate.search(searchQuery, Worker.class,IndexCoordinates.of("lxes2011")).getSearchHits();
        //此处是遍历出来实体类
         for (SearchHit<Worker> searchHit : workers) {
         //!!!!!!
            Worker content = searchHit.getContent();
            System.out.println(content);
          }
        System.err.println(workers);
    }
    //词条查询(精确查询)
    @Test
    public void t2(){
        //词条查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.termQuery("company","pdd")).build();
        //分页查询
        searchQuery.setPageable(PageRequest.of(2,100, Sort.by(Sort.Order.desc("id"))));
        List<SearchHit<Worker>> workers=restTemplate.search(searchQuery, Worker.class,IndexCoordinates.of("lxes2011")).getSearchHits();
        System.err.println(workers);
    }
    //模糊查询
    @Test
    public void t3(){
        //模糊查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.fuzzyQuery("name","88")).build();
        //分页查询
        searchQuery.setPageable(PageRequest.of(2,100, Sort.by(Sort.Order.desc("id"))));
        List<SearchHit<Worker>> workers=restTemplate.search(searchQuery, Worker.class,IndexCoordinates.of("lxes2011")).getSearchHits();
        System.err.println(workers);
    }
    //通配符查询
    @Test
    public void t4(){
        //通配符查询 *任意字符 ?单个字符
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.wildcardQuery("name","*88*")).build();
        //分页查询
        searchQuery.setPageable(PageRequest.of(2,100, Sort.by(Sort.Order.desc("id"))));
        List<SearchHit<Worker>> workers=restTemplate.search(searchQuery,   	Worker.class,IndexCoordinates.of("lxes2011")).getSearchHits();
        System.err.println(workers);
    }
}

补充--------

QueryBuilders.matchQuery()
会将搜索词分词,再与目标查询字段进行匹配,若分词中的任意一个词与目标字段匹配上,则可查询到。(任意一个完整的词语 后续不满足一整个单词也可以)
列如:添加语句i like eating and kuing
param = “i” 可查出i
param = “i li” 可查出
param = “i like” 可查出
param = “i like eat” 可查出
param = “and” 可查出
param = “kuing” 可查出
param = “ku” 查不出
param = “li” 查不出
param = “eat” 查不出

QueryBuilders.matchPhraseQuery()
会精确匹配查询的短语,需要全部单词和顺序要完全一样,标点符号除外。(满足顺序并且满足一整个单词 后续不满足一整个单词不可以)
列如:添加语句i like eating and kuing
param = “i” 可查出i
param = “i li” 查不出
param = “i like” 可查出
param = “i like eat” 查不出
param = “and” 可查出
param = “kuing” 可查出
param = “ku” 查不出
param = “li” 查不出
param = “eat” 查不出

** QueryBuilders.matchPhrasePrefixQuery()**
它允许对最后一个词条前缀匹配(可以半个单词就可以查到)
列如:添加语句i like eating and kuing
param = “i” 可查出i
param = “i li” 可查出
param = “i like” 可查出
param = “i like eat” 可查出
param = “and” 可查出
param = “kuing” 可查出
param = “ku” 可查出
param = “li” 可查出
param = “eat” 可查出

QueryBuilders.termQuery(“supplierName”,param)
查询内容是什么,就会按照什么去查询,并不会解析查询内容,对它分词(输入单词 不会进行分词 只查看单个单词有没有语句中包含)
列如:添加语句i like eating and kuing
param = “i” 可查出i
param = “i li” 查不出
param = “i like” 查不出
param = “i like eat” 查不出
param = “and” 可查出
param = “kuing” 可查出
param = “ku” 查不出
param = “li” 查不出
param = “eat” 查不出

10、搜索建议

创建索引

PUT /job
POST /job/_mapping
{
  "properties": {
      "_class": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "id":{
        "type": "long"
      },
      "name": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          },
          "suggest": {
            "type": "completion",
            "analyzer": "simple",
            "preserve_separators": true,
            "preserve_position_increments": true,
            "max_input_length": 50
          }
        }
      },
      "durl" : {
        "type" : "text"
      },
      "salary":{
        "type": "keyword"
      }
      
  }
}

搜索建议 msg = java 后面展示出很多嗯java------相关的

  @Override
    public List<String> get(String msg) {
        List<String> list = new ArrayList<>();
        CompletionSuggestionBuilder builder = new CompletionSuggestionBuilder("name.suggest");
        builder.size(50).prefix(msg);
        //查询本地化查询
        SuggestBuilder suggestBuilder = new SuggestBuilder();
        suggestBuilder.addSuggestion("name", builder);
        //执行搜索建议查询
        SearchResponse response = elasticsearchRestTemplate.suggest(suggestBuilder, IndexCoordinates.of("job"));
        Suggest suggest = response.getSuggest();
        Suggest.Suggestion name = suggest.getSuggestion("name");
        for (Object o : name.getEntries()) {
            Suggest.Suggestion.Entry o1 = (Suggest.Suggestion.Entry) o;
            for (Object o2 : o1.getOptions()) {
                Suggest.Suggestion.Entry.Option o21 = (Suggest.Suggestion.Entry.Option) o2;
                list.add(o21.getText().toString());
            }
        }
        return list;
    }

11、聚合查询

聚合操作

聚合操作可以查看 比方:某个商品在条件后 聚合商品名字 查看哪个店铺以及查看这个商品在哪家店铺
如下图: 条件:(笔记本 价格区间) 聚合:(商家名字) 结果:商品可能来自同一家商家 名字聚合后就只有一个 还可以看这家商品符合条件有几个

本图转载
在这里插入图片描述

-----------------上述只是案例 跟下述案例不一样

同10创建索引

实体类

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
//主要
@Document(indexName = "job")
//通过Job.of("张三")可获取job对象   结合@NotNull使用
@RequiredArgsConstructor(staticName = "of")
public class Job {
	//主要
    @Id
    private Integer id;
    @NotNull
    private String name;
    private String durl;
    private String salary;

}
     NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        TermsAggregationBuilder size = AggregationBuilders.terms("group").field("name.keyword").size(9999);
        NativeSearchQuery build = nativeSearchQueryBuilder.withAggregations(size).build();
        SearchHits<Job> searchs = elasticsearchRestTemplate.search(build, Job.class, IndexCoordinates.of("job"));

        AggregationsContainer<?> aggregations = searchs.getAggregations();
        Aggregations aggregations1 = (Aggregations) aggregations.aggregations();
        Aggregation group = aggregations1.get("group");
        List<? extends Terms.Bucket> buckets = ((ParsedStringTerms) group).getBuckets();
        for (Terms.Bucket bucket : buckets) {
            //获取字段值
            String key = (String) bucket.getKey();
            long val = bucket.getDocCount();// 聚合字段对应的数量
            System.out.println(key + ":::::" + val);
        }

12、高亮显示


    @RequestMapping("/test")
    public List<Job> test(String msg) {
        //多个字段进行匹配
        MultiMatchQueryBuilder queryBuilder = new MultiMatchQueryBuilder(msg, "name", "salary");
        //要高亮的字段
        HighlightBuilder field = new HighlightBuilder()
                .preTags("<font color='red'>")
                .postTags("</font>")
                .field("name")
                .field("salary");
        NativeSearchQuery build = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withHighlightBuilder(field)
                .build();
        SearchHits<Job> searchHits = elasticsearchRestTemplate.search(build, Job.class, IndexCoordinates.of("job"));
        List<Job> jobs = Lists.newArrayList();
        for (SearchHit<Job> searchHit : searchHits) {
            //获取高亮显示内容  当条件中的字段命中后进行高亮显示
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            //查看有没有高亮显示条件命中的   比如 name = 张三   salary没有命中  只高亮name
            String salary = highlightFields.get("salary") == null ? searchHit.getContent().getSalary() : highlightFields.get("salary").get(0);
            String name = highlightFields.get("name") == null ? searchHit.getContent().getName() : highlightFields.get("name").get(0);
            searchHit.getContent().setSalary(salary);
            searchHit.getContent().setSalary(name);
            jobs.add(searchHit.getContent());
        }

        return jobs;

    }

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张航柯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值