ElasticSearch

为什么要学习ElasticSearch

  • 用SQL进行模糊查询:like %%,如果是大数据,就十分的慢。

Lucene

Lucene是一套信息检索工具包,jar包,不包含搜索引擎系统,它包含索引结构,读写索引的工具、排序、搜索规则。

Lucene和ElasticSearch的关系

ElasticSearch是基于Lucene做了一些封装和增强

什么是ElasticSearch

ElasticSearch,简称为es,es是一个开源的高扩展的分布式全文检索引擎,它可以实现存储、检索数据,扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使用java开发并使用lucene作为其核心来实现所有索引和搜索的功能,它通过简单的restful api来隐藏lucene的复杂性,从而让全文搜索变得简单。
在2016年,ElasticSearch已超过Solr,成为排名第一的搜索引擎。

历史

多年前,Shay Banon 一个刚结婚不久的失业开发者,由于他老婆要去伦敦学习厨师,他便跟着去了,在他找工作的过程中,为了给他妻子构建一个食谱的搜索引擎,他开始构建一个早期版本的lucene。
直接基于lucene工作会比较困难,所以Shay开始抽象Lucene代码以便java程序员可以在应用中添加搜索功能,他发布了他的第一个开源项目,叫做Compass。
后来Shay找到一份工作,这份工作处在高性能和内存数据网络的分布式环境中,因此高性能的,分布式的搜索引擎也是理所当然的,然后他决定重写Compass库使其成为一个独立的服务叫做ElasticSearch。
第一个公开版出现在2010年,在那之后ElasticSearch已经成为Github上最受欢迎的项目之一,代码贡献者超过300人,一家主营ElasticSearch的公司就此成立,他们一边提供商业支持一边开发新功能,不过ElasticSearch将永远开源且对所有人可用。

ElasticSearch和Solr的区别

ElasticSearch介绍

ElasticSearch是一个分布式搜索和分析引擎,它让你以前所未有的速度处理大数据成为可能。
它用于全文搜索结构化搜索分析以及将这三种混合使用。
百科使用ElasticSearch提供全文搜索并高亮关键字,以及输入实时搜索和搜索纠错等搜索建议。
英国卫报使用ElasticSearch结合用户日志和社交网络数据提供给他们的编辑以实时的反馈,以便及时了解对新发表的文章的回应。
StackOverflow结合全文搜索与地理位置查询,以及more-like-this功能来找到相关的问题和答案。
Github使用ElasticSearch检索1300亿行的代码。
ElasticSearch是一个基于Apache Lucene的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进性能最好的、功能最全的搜索引擎库,es也使用java开发并使用lucene作为其核心来实现所有索引和搜索的功能,它通过简单的restful api来隐藏lucene的复杂性,从而让全文搜索变得简单。

Solr介绍

Solr采用java开发,它是基于Lucene的全文搜索服务器,Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置可扩展、并对索引、搜索性能进行了优化。
Solr可以独立运行,运行在jetty,tomcat等这些servlet容器中,Solr索引的实现方法很简单,用post方法向solr服务器发送一个描述field及其内容的xml文档,solr根据xml文档添加、删除,更新索引。

ElasticSearch和Solr比较

  • 当单纯的对已经有的数据进行搜索时,Solr更快。
  • 当实时建立索引时,Solr会产生io阻塞,查询性能比较差,ElasticSearch具有明显的优势。
  • 随着数据量的增加,Solr的搜索效率会变得更低,而ElasticSearch却没有明显的变化。
  • es基本是开箱即用,非常简单,Solr安装复杂一点。
  • Solr利用Zookeeper进行分布式管理,而es自身带有分布式协调管理功能
  • Solr支持更多格式的数据,而es本身更注重于核心功能,高级功能多有第三方插件支持,例如图形化界面需要kibana友好支撑。
  • Solr查询快,但更新索引时慢,用于电商等查询多的应用。
  • es建立索引快,即实时查询快,用于facebook新浪等搜索。
  • Solr是传统搜索应用的有力解决方案,但es更适用于新兴的实时搜索应用,
  • Solr比较成熟,有一个更大,更成熟的用户,开发和贡献者社区,而es相对开发维护者较少,更新太快,学习使用成本较高。

ElasticSearch安装

最低要求:JDK1.8

下载

官网:https://www.elastic.co/cn/

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

window 下安装!

1.解压即可使用
在这里插入图片描述
2.熟悉目录

  • bin :启动文件
  • config:配置文件、log4j2:日志配置文件、jvm.options :java虚拟机相关的配置、elasticsearch.yml :elasticsearch的配置文件! 默认端口9200!跨域
  • lib相关jar包
  • logs:日志
  • modules:功能模块
  • plugins:插件

3.启动
在这里插入图片描述
在这里插入图片描述

  • 访问9200
    在这里插入图片描述

安装可视化界面 es head的插件

下载地址:https://github.com/mobz/elasticsearch-head/

  • 下载后解压

在这里插入图片描述

  • 先安装一下依赖
    在这里插入图片描述

  • 依赖已下好
    在这里插入图片描述
    在这里插入图片描述

  • 这里有个跨域的问题
    在这里插入图片描述

  • 配置跨域
    在这里插入图片描述
    在这里插入图片描述

  • 重启ElasticSearch
    在这里插入图片描述

  • 新建索引 ,索引就相当于一个数据库
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

这个head就把它当做数据展示工具!我们后面所有的查询,都用kibana来做。

什么是ELK

ELK是ElasticSearch,Logstash,Kibana三大开源框架字母大写简称,市面上也被称为Elastic Stack,其中ElasticSearch是一个基于Lucene,分布式,通过Restful方式进行交互的搜索平台框架,类似百度、谷歌这种大数据全文搜索引擎的场景都可以使用Elasticsearch作为底层支持框架,提供的搜索能力确实强大。
Logstash是ELK的中央数据流引擎用于从不同目标收集不同格式的数据,经过过滤后支持输出到不同目的地。
Kibana可以将ElasticSearch的数据通过友好的页面展示出来,提供实时分析的功能。

市面上很多开发只要提到ELK,都说它是一个日志分析架构技术栈总称,但实际上ELK不仅仅适用于日志分析,它还可以支持其它任何数据分析和收集的场景,日志分析和收集只是更具代表性,并非唯一性。
在这里插入图片描述

安装kibana

Kibana是一个针对于ElasticSearch的开源分析及可视化平台,用来搜索,查看交互存储在ElasticSearch索引中的数据,使用kibana可以通过各种图表进行高级数据分析及展示,kibana让海量数据更容易理解,它操作简单,基于浏览器的用户界面可以快速创建仪表板,实时显示ElasticSearch查询动态,设置kibana非常简单,无需编码或者额外的基础架构,几分钟内就可以完成kibana安装并启动ElasticSearch索引监测。
下载地址:https://www.elastic.co/cn/downloads/kibana
在这里插入图片描述

  • 下载后解压
    在这里插入图片描述

启动测试

在这里插入图片描述

  • 注意启动kibana的时候,ElasticSearch也要启动
    在这里插入图片描述
  • 访问端口测试
    在这里插入图片描述
    在这里插入图片描述
  • 之后所有的操作都在这里进行编写
    在这里插入图片描述
  • 汉化
    在这里插入图片描述
    在这里插入图片描述
  • 重启kibana
    在这里插入图片描述

ElasticSearch核心概念

概述

在前面的学习中,我们已经掌握了es是什么,同时也把es的服务已经安装启动,那么es是如何去存储数据,数据结构是什么,又是如何实现搜索的呢,我们先来聊聊ElasticSearch的相关概念把
集群节点索引类型文档分片映射是什么?

elasticsearch是面向文档,关系型数据库和elasticsearch客观的对比!

Relational DBElasticSearch
数据库(database)索引(indices)
表(tables)types
行(rows)documents
字段(columns)fields

elasticsearch中可以包含多个索引,每个索引中可以包含多个类型,每个类型下又包含多个文档,每个文档中又包含多个字段

IK分词器插件

分词:把一段中文或者别的划分成一个个的关键字,我们在搜索的时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词。
IK提供了两个分词算法:ik_smart,最少切分和ik_max_word,为最细粒度划分。

安装IK分词器

下载地址:https://github.com/medcl/elasticsearch-analysis-ik

  • 下载完毕后,放入到elasticsearch即可
    在这里插入图片描述
  • 重启观察ElasticSearch,插件被加载了
    在这里插入图片描述
  • 也可以通过 elasticsearch-plugin list这个命令来查看加载进来的插件
    在这里插入图片描述
  • 使用kibana进行测试

不同分词器的效果

  • ik_smart,最少切分
    在这里插入图片描述
  • ik_max_word,为最细粒度划分
    在这里插入图片描述
  • 发现问题:聂礼兵这个名字被拆开了!
  • 这种需要的词,需要自己加到我们的分词器的字典中!
    在这里插入图片描述

ik分词器增加自己的配置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 重启es,加载了刚刚咱自己加的那个字典
    在这里插入图片描述

-现在就可以识别了
在这里插入图片描述

Rest风格

一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件,它主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

  • 基本Rest命令说明:
methodurl地址描述
PUTlocalhost9200/索引名称/类型名称/文档id创建文档(指定文档id)
POSTlocalhost9200/索引名称/类型名称创建文档(随机文档id)
POSTlocalhost9200/索引名称/类型名称/文档id/_update修改文档
DELETElocalhost9200/索引名称/类型名称/文档id删除文档
GETlocalhost9200/索引名称/类型名称/文档id查询文档通过文档id
POSTlocalhost9200/索引名称/类型名称/文档id查询所以数据

基础测试

1.创建一个索引

  • 启动 head-master
    在这里插入图片描述
  • 2.访问
    在这里插入图片描述

PUT /索引名/类型名/文档id
{
请求体
}

在这里插入图片描述

  • 3.索引创建成功!

在这里插入图片描述

  • 4.数据浏览,完成了自动增加了索引,在初期可以把它当做数据库学习
    在这里插入图片描述
那么name这个字段没有指定类型,在我们数据库关系型数据库,是需要指定类型的。
  • 字符串类型:text,keyword
  • 数值类型:long,integer,short,byte,double,float,halffloat,scaledfloat
  • 日期类型:date
  • 布尔值类型:boolean
  • 二进制类型:binary

5.指定字段的类型
在这里插入图片描述
在这里插入图片描述

  • 6.获得指定类型的规则,可以通过GET请求获取具体的信息
    在这里插入图片描述
  • 7.查看默认的信息
    在这里插入图片描述
  • 如果自己的文档字段没有指定,那么es就会给我们默认配置字段类型!
  • 通过get _cat/可以获得es的当前的很多信息
    在这里插入图片描述

修改 提交还是使用PUT即可! 然后覆盖!

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

删除索引
通过delete命令实现删除,根据你的请求来判断是删除索引还是删除文档记录
使用restful风格是es推荐使用的

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

关于文档 基本操作

基本操作

1.添加数据

POST nie/user/1
{
  "name":"清石",
  "age":3,
  "desc": ["明月松间照","清泉石上流"]
}

在这里插入图片描述
2.获取数据 GET

在这里插入图片描述
3.更新数据 PUT
在这里插入图片描述
4.POST _update,推荐使用这种更新方式!
在这里插入图片描述
5.简单的搜索

  • GET nie/user/1
  • 简单的条件查询,可以根据默认 的映射规则,产生基本的查询!
    在这里插入图片描述
    6.复杂操作搜索 select (排序,分页,高亮,模糊查询,精准查询!)
    在这里插入图片描述
    在这里插入图片描述
  • 输出结果,不想要那么多!
    在这里插入图片描述
  • 之后使用java操作es,所有的方法和对象就是这里面的key!

排序

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

分页查询

在这里插入图片描述

布尔值查询
must (and) ,所有的条件都要符合
在这里插入图片描述

  • should(or) ,一部分的条件符合
    在这里插入图片描述
  • must_not,不包括查询条件的信息
    在这里插入图片描述
  • 过滤器 filter
    在这里插入图片描述
  • 匹配多个条件
    在这里插入图片描述

精确查询
term 查询是直接通过倒排序索引指定的词条进程精确的查找的!

关于分词:

  • term,直接查询精确的
  • match,会使用分词器解析!(先分析文档,然后在通过分析的文档进行查询!)

两个类型:

  • text:会被分词器解析
  • keyword:不会被分词器解析

高亮查询

在这里插入图片描述

  • 自定义高亮
    在这里插入图片描述

集成SpringBoot

找官方文档:https://www.elastic.co/guide/index.html

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1.找到依赖

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.10.2</version>
</dependency>

2.找对象
在这里插入图片描述

3.分析类中的方法

配置基本的项目

注意: 一定要保证我们的导入的依赖和我们的es版本一致
在这里插入图片描述

  • pom.xml
<properties>
        <java.version>1.8</java.version>
        <!--自己定义es版本依赖,保证和本地一致-->
        <elasticsearch.version>7.10.2</elasticsearch.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-configuration-processor</artifactId>
                        </exclude>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

在这里插入图片描述

  • ElasticSearchClientConfig
@Configuration
public class ElasticSearchClientConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient(){
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("127.0.0.1", 9200, "http")));
        return client;
    }
}

具体的api测试

1.创建索引

@SpringBootTest
class NieEsApiApplicationTests {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    //索引的创建
    @Test
    public void testCreateIndex() throws IOException {
        //1.创建索引请求
        CreateIndexRequest request=new CreateIndexRequest("niu_index");
        //2.客户端执行请求,indicesClient,请求后获得响应
        CreateIndexResponse createIndexResponse=
                restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);
    }
}
//测试获取索引
    @Test
    public void testExistIndex() throws IOException{
        GetIndexRequest request=new GetIndexRequest("niu_index");
        //判断索引是否存在
        boolean exists=restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println("是否存在:"+exists);
    }
    //测试删除索引
    @Test
    public void testDeleteIndex() throws IOException {
        DeleteIndexRequest request=new DeleteIndexRequest("niu_index");
        //删除
        AcknowledgedResponse delete=restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
        System.out.println(delete.isAcknowledged());
    }

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

爬虫

数据问题? 数据库获取,消息队列中获取中,都可以成为数据源,爬虫
爬取数据:获取请求返回的页面信息,筛选出我们想要的数据就可以了!

jsoup包!
1.导入依赖
在这里插入图片描述

@Component
public class HtmlParseUtil {


        public List<Content>parseJD (String keywords) throws Exception {
            //获取请求 https://search.jd.com/Search?keyword=java
            String url = "https://search.jd.com/Search?keyword="+keywords;
            //解析网页
            Document document = Jsoup.parse(new URL(url), 30000);
            //所有你在js中可以使用的方法,这里都能用!
            Element element = document.getElementById("J_goodsList");
            //获取所有的li元素
            Elements elements = element.getElementsByTag("li");
            //获取元素中的内容,这里el就是每一个li标签了

            ArrayList<Content> goodsList = new ArrayList<>();
            for (Element el : elements) {
                String img = el.getElementsByTag("img").eq(0).attr("data-lazy-img");

                String price = el.getElementsByClass("p-price").eq(0).text();
                String title = el.getElementsByClass("p-name").eq(0).text();

           Content content=new Content();
            content.setImg(img);
           content.setPrice(price);
           content.setTitle(title);
            goodsList.add(content);

            }
            return goodsList;
        }

}

//业务编写
@Service
public class ContentService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;


    //1.解析数据放入es索引中
    public Boolean parseContent(String keywords) throws Exception{
        List<Content> contents=new HtmlParseUtil().parseJD(keywords);
        //把查询到的数据放入es中
        BulkRequest bulkRequest=new BulkRequest();
        bulkRequest.timeout("2m");
      for(int i=0;i<contents.size();i++){
          bulkRequest.add(new IndexRequest("jd_goods").source(JSON.toJSONString(contents.get(i)),  XContentType.JSON));
      }
        BulkResponse bulk=restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
      return !bulk.hasFailures();
    }

    //2.获取这些数据实现搜索功能
    public List<Map<String,Object>> searchPage(String keyword,int pageNo,int pageSize) throws IOException {
            if(pageNo<=0){
                pageNo=1;
            }
            //条件搜索
        SearchRequest searchRequest=new SearchRequest("jd_goods");
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();

        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);

        //精准匹配
        TermQueryBuilder termQueryBuilder= QueryBuilders.termQuery("title",keyword);
        sourceBuilder.query(termQueryBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        //执行搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse=restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);

        //解析结果
        ArrayList<Map<String,Object>> list=new ArrayList<>();
        for (SearchHit documentFields:searchResponse.getHits().getHits()){
            list.add(documentFields.getSourceAsMap());
        }
        return list;
    }


    //2.获取这些数据实现搜索高亮功能
    public List<Map<String,Object>> searchPage1(String keyword,int pageNo,int pageSize) throws IOException {
        if(pageNo<=0){
            pageNo=1;
        }
        //条件搜索
        SearchRequest searchRequest=new SearchRequest("jd_goods");
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();

        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);

        //精准匹配
        TermQueryBuilder termQueryBuilder= QueryBuilders.termQuery("title",keyword);
        sourceBuilder.query(termQueryBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
         //高亮
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.requireFieldMatch(false);
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        sourceBuilder.highlighter(highlightBuilder);
        //执行搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse=restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);

        //解析结果
        ArrayList<Map<String,Object>> list=new ArrayList<>();
        for (SearchHit hit:searchResponse.getHits().getHits()){
            Map<String, HighlightField> highlightFields=hit.getHighlightFields();
            HighlightField title=highlightFields.get("title");
            Map<String,Object> sourceAsMap=hit.getSourceAsMap();//原来的结果
            //解析高亮的字段,将原来的自字段换成我们高亮的字段即可!
            if(title!=null){
                Text[] fragments=title.fragments();
                String n_title="";
                for (Text text:fragments){
                    n_title +=text;
                }
                sourceAsMap.put("title",n_title);
            }
              list.add(sourceAsMap);
        }
        return list;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

南离火

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

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

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

打赏作者

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

抵扣说明:

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

余额充值