搜索引擎Elasticsearch基础与实践

倒排索引

将文档中的内容分词,然后形成词条。记录每条词条与数据的唯一表示如id的对应关系,形成的产物就是倒排索引,如下图:
在这里插入图片描述

ElasticSearch数据的存储和搜索原理

在这里插入图片描述
这里的索引库相当于mysql中的database。一个文档(document)是一个可被索引的基础信息单元。

查询逻辑:根据词条去匹配查询,可以对搜索关键字先分词在查询。es中自动会对词条排序,形成一个树形的结构

ElasticSearch概念

  • ElasticSearch是一个基于Lucene的搜索服务器
  • 是一个分布式、高扩展、高实时的搜索与数据分析引擎
  • 基于RESTfur web接口
  • 流行的企业级搜索引警 Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种
  • ElasticSearch和MySql分工不同,MySQL负责存储数据,ElasticSearch负责搜索数据

应用场景

  • 搜索:海量数据的查询
  • 日志数据分析
  • 实时数据分析

映射(maping)

相当于数据库的表结构,也就是定义不同字段的类型
在这里插入图片描述
简单数据类型
1、字符串

  • text:会分词,不支持聚合
  • keyword:不会分词,将全部内容作为一个词条,支持聚合

2、数值
3、布尔 boolean
4、二进制 .binary
范国类型
integer range, float range, long range, double range, date range

复杂数据类型

  • 数组:[]
  • 对象:()

文档操作

添加文档,指定id
put 索引/_doc/id{添加内容}

添加文档,不指定id
post 索引/_doc{添加内容}

查询指定id的文档
get 索引/_doc/id

查询所有文档
get 索引/_doc/_search

IK分词器

java开发的轻量级的中文分词器

springboot整合es

1、引入es的RestHighLevelClient依赖:

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

2、初始化RestHighLevelClient:
在这里插入图片描述
导入client

@Autowiredprivate 
RestHighLevelClient client;

索引操作

操作索引对象的对象是indicesClient,使用create函数
参数:
Createindexrequest、请求类型
获取为getIndexrequest
删除为Deleteindexrequest
在这里插入图片描述也可以添加mapping在这里插入图片描述

文档操作

获取操作文档的对象:indexrequest
添加需要在indexrequest中设定索引、id、以及添加的数据(JSON)
修改:indexrequest
查询:getrequest
在这里插入图片描述
在这里插入图片描述

Bulk批量操作

在这里插入图片描述

Elient.bulk(bulkRequest , RequestOptions.DEFAULT);

解释:
1、创建mybatis的map映射,并创建实例对象接收
2、查询mysql数据、存入到对象中
3、创建bulkrequest对象,操作批量操作
4、遍历查询结果,对不符合es映射规定的字段格式的进行转换、并添加到indexrequest中,在添加到bulkrequest中
6、调用client的bulk操作,批量插入

模糊查询

1、wildcard查询:会对查询条件进行分词。还可以使用通配符?(任意单个字符)和 * (0个或多个字符)
2、prefix查询:前缀查询

# wildcard 查询。查询条件分词,模糊查询
GET goods/_search
	"query":(
		"wildcard":{
			"title":
				"value":"华?

在这里插入图片描述
java代码:
在这里插入图片描述

前缀查询;

在这里插入图片描述

范围查询

在这里插入图片描述java代码:
同样只需要修改query这个参数信息就行
在这里插入图片描述

布尔查询

脚本:
boolQuery:对多个查询条件连接。连接方式:
must (and):条件必须成立
must not (not):条件必须不成立
should (or):条件可以成立
filter: 条件必须成立,性能比must高。不会计算得分
在这里插入图片描述

高亮查询

高亮的三要素:
高亮字段、前缀、后缀
在这里插入图片描述
java代码:
1、设置高亮

//设置高亮
HighlightBuilder highlighter = new HighlightBuilder()://
设置三要素
highlighter.field("title");
highlighter.preTags("<font color='red'>");
highlighter.postTags("</font>");

2、用高亮的结果代替原有的结果

// 获取高亮结果,替换goods中的title
Map<String,HighlightField> highlightFields = hit,getHighlightFields().
HighlightField HighlightField = highlightFields.get("title");
Text[] fragments = HighlightField.fragments();//这里的fragments是表示我们的拿到是一个一个的高亮片段,包含了不同区域的高亮
//替换goods.setTitle(fragments[e].tostring()):

第二步为从查询到hit中的hightlight代替原有的字段

2、黑马头条es实践

2.1)搭建搜索微服务

(1)导入 heima-leadnews-search
(2)在heima-leadnews-service的pom中添加依赖

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

(3)nacos配置中心leadnews-search

spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
elasticsearch:
  host: 192.168.200.130
  port: 9200
2.2) 搜索接口定义
package com.heima.search.controller.v1;

import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

@RestController
@RequestMapping("/api/v1/article/search")
public class ArticleSearchController {


    @PostMapping("/search")
    public ResponseResult search(@RequestBody UserSearchDto dto) throws IOException {
        return null;
    }
}

UserSearchDto

package com.heima.model.search.dtos;

import lombok.Data;

import java.util.Date;


@Data
public class UserSearchDto {

    /**
    * 搜索关键字
    */
    String searchWords;
    /**
    * 当前页
    */
    int pageNum;
    /**
    * 分页条数
    */
    int pageSize;
    /**
    * 最小时间
    */
    Date minBehotTime;

    public int getFromIndex(){
        if(this.pageNum<1)return 0;
        if(this.pageSize<1) this.pageSize = 10;
        return this.pageSize * (pageNum-1);
    }
}
2.3) 业务层实现

创建业务层接口:ApArticleSearchService

package com.heima.search.service;

import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.common.dtos.ResponseResult;

import java.io.IOException;

public interface ArticleSearchService {

    /**
     ES文章分页搜索
     @return
     */
    ResponseResult search(UserSearchDto userSearchDto) throws IOException;
}

实现类:

package com.heima.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.service.ArticleSearchService;
import com.heima.utils.thread.AppThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ArticleSearchServiceImpl implements ArticleSearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * es文章分页检索
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult search(UserSearchDto dto) throws IOException {

        //1.检查参数
        if(dto == null || StringUtils.isBlank(dto.getSearchWords())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.设置查询条件
        SearchRequest searchRequest = new SearchRequest("app_info_article");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //布尔查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        //关键字的分词之后查询
        QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(dto.getSearchWords()).field("title").field("content").defaultOperator(Operator.OR);
        boolQueryBuilder.must(queryStringQueryBuilder);

        //查询小于mindate的数据
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime().getTime());
        boolQueryBuilder.filter(rangeQueryBuilder);

        //分页查询
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(dto.getPageSize());

        //按照发布时间倒序查询
        searchSourceBuilder.sort("publishTime", SortOrder.DESC);

        //设置高亮  title
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("<font style='color: red; font-size: inherit;'>");
        highlightBuilder.postTags("</font>");
        searchSourceBuilder.highlighter(highlightBuilder);


        searchSourceBuilder.query(boolQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);


        //3.结果封装返回

        List<Map> list = new ArrayList<>();

        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            String json = hit.getSourceAsString();
            Map map = JSON.parseObject(json, Map.class);
            //处理高亮
            if(hit.getHighlightFields() != null && hit.getHighlightFields().size() > 0){
                Text[] titles = hit.getHighlightFields().get("title").getFragments();
                String title = StringUtils.join(titles);
                //高亮标题
                map.put("h_title",title);
            }else {
                //原始标题
                map.put("h_title",map.get("title"));
            }
            list.add(map);
        }

        return ResponseResult.okResult(list);

    }
}
2.4) 控制层实现

新建控制器ArticleSearchController

package com.heima.search.controller.v1;

import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.search.service.ArticleSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

@RestController
@RequestMapping("/api/v1/article/search")
public class ArticleSearchController {

    @Autowired
    private ArticleSearchService articleSearchService;

    @PostMapping("/search")
    public ResponseResult search(@RequestBody UserSearchDto dto) throws IOException {
        return articleSearchService.search(dto);
    }
}
3.5.5) 测试

需要在app的网关中添加搜索微服务的路由配置

#搜索微服务
- id: leadnews-search
 uri: lb://leadnews-search
 predicates:
   - Path=/search/**
 filters:
   - StripPrefix= 1

新增文章同步添加索引

在这里插入图片描述
1、把SearchArticleVo放到model工程下
2、文章微服务的ArticleFreemarkerService中的buildArticleToMinIO方法中收集数据并发送消息

    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    /**
     * 送消息,创建索引
     * @param apArticle
     * @param content
     * @param path
     */
    private void createArticleESIndex(ApArticle apArticle, String content, String path) {
        SearchArticleVo vo = new SearchArticleVo();
        BeanUtils.copyProperties(apArticle,vo);
        vo.setContent(content);
        vo.setStaticUrl(path);

        kafkaTemplate.send(ArticleConstants.ARTICLE_ES_SYNC_TOPIC, JSON.toJSONString(vo));
    }

3、文章微服务集成kafka发送消息

kafka:
    bootstrap-servers: 192.168.200.130:9092
    producer:
      retries: 10
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer

4、搜索微服务中添加kafka的配置,nacos配置如下

spring:
  kafka:
    bootstrap-servers: 192.168.200.130:9092
    consumer:
      group-id: ${spring.application.name}
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

5.定义监听接收消息,保存索引数据

@Component
@Slf4j
public class SyncArticleListener {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @KafkaListener(topics = ArticleConstants.ARTICLE_ES_SYNC_TOPIC)
    public void onMessage(String message){
        if(StringUtils.isNotBlank(message)){

            log.info("SyncArticleListener,message={}",message);

            SearchArticleVo searchArticleVo = JSON.parseObject(message, SearchArticleVo.class);
            IndexRequest indexRequest = new IndexRequest("app_info_article");
            indexRequest.id(searchArticleVo.getId().toString());
            indexRequest.source(message, XContentType.JSON);
            try {
                restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
                log.error("sync es error={}",e);
            }
        }

    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/120793.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【基带开发】AD9361通信基础:复数乘法 除法

复数 是实数和虚数的组合 例子&#xff1a;3.6 4i, −0.02 1.2i, 25 − 0.3i, 0 2i 乘法 除法

在maven官网中如何下载低版本的maven

链接&#xff1a;https://archive.apache.org/dist/maven/maven-3/

vscode设置pycharm中的项目路径和debug方法

真大佬在这 真大佬在这 必须给大佬star 命令行运行&#xff1a; export PYTHONPATH:pwd:/home/bennie/bennie/bennie_project/AI_Lab python main.py 当关闭此命令行时&#xff0c;临时路径会清除&#xff0c;可以将上述export的整条语句&#xff0c;加入~/.bashrc中 该命令中…

JDBC SQL Server Source Connector: 一览与实践

在快速发展的数据驱动业务环境中&#xff0c;确保数据在各个系统间高效、准确地同步至关重要。为了进一步的数据处理和分析&#xff0c;经常需要将这些数据同步到其他数据处理系统。Apache SeaTunnel 提供了一个强大而灵活的数据集成框架&#xff0c;使得从 SQL Server 到其他系…

「随笔」浅谈2023年云计算的发展趋势

在2023年&#xff0c;云计算的发展趋势将受到政治、经济、社会和科技四个维度的影响。以下是对这些维度的具体分析&#xff1a; 1.1 政治维度&#xff1a; 全球政策推动&#xff1a; 随着全球各国政策对云计算的重视程度不断提高&#xff0c;云计算服务将获得更广泛的市场准入…

MES管理系统中常规的生产建模有哪些

随着制造业的快速发展&#xff0c;MES生产管理系统已经成为了现代制造业不可或缺的核心系统。MES通过对生产过程进行建模&#xff0c;实现了生产过程的可视化、可控制和可优化&#xff0c;为企业提供了全方位的生产管理解决方案。本文将深化对MES管理系统及其主要生产模型的理解…

『MySQL快速上手』-⑥-表的约束

文章目录 1.空属性2.默认值3.列描述4.zerofill5.主键6.自增长7.唯一键8.外键9.综合案例 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&#xff0c;从业务逻辑角度保证数据的正确性。 1.空…

第一个ARM程序裸板点灯

硬件知识LED原理图 如何点亮一个LED灯&#xff1f; 看原理图&#xff0c;确定控制LED的引脚。看主芯片的芯片手册&#xff0c;确定如何设置控制这个引脚。写程序。 LED有插脚封装的、贴片封装的。 它们长得完全不一样&#xff0c;因此我们在原理图中把它们抽象出来。 点亮…

[SSD综述 1.5] SSD 主控和固件核心功能详解(万字)

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 1. 主控概述1.1 主控作用 2. 主控的硬件功能和实现2.1 主控处理器2.2 闪存、主机接口2.3 主控纠错2.4 断电保护 3 固件功能3.1 FTL3.2 预留空间(Over-provisioning)3.3 Trim3.4 写入放大(Write amplification)3.5 …

Django初窥门径-自定义附件存储模型

前言 Django自带了一个名为FileField的字段&#xff0c;用于处理文件上传。然而&#xff0c;有时我们需要更多的控制权&#xff0c;例如定义文件的存储路径、文件名以及文件类型。在本篇文章中&#xff0c;我们将探讨如何自定义Django附件存储模型。 创建attachment应用 pyt…

【计算机网络】物理层知识

目录 1、物理层的基本概念 2、数据通信的基础知识 2.1、数据通信系统模型 2.2、信道的几个基本概念 3、物理层下面的传输媒体 4、信道复用技术 1、物理层的基本概念 物理层考虑的是怎样才能在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是指具体的 传输媒…

数据结构:Map和Set(2):相关OJ题目

目录 136. 只出现一次的数字 - 力扣&#xff08;LeetCode&#xff09; 771. 宝石与石头 - 力扣&#xff08;LeetCode&#xff09; 旧键盘 (20)__牛客网 (nowcoder.com) 138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 692. 前K个高频单词 - 力扣&#xff08…

CDN加速技术:降低企业云服务成本的有效利用

在当今数字化时代&#xff0c;云服务已经成为企业运营的不可或缺的一部分。然而&#xff0c;与此同时&#xff0c;云服务的需求也在不断增长&#xff0c;使企业不得不应对更大的数据传输和负载。这就引出了一个关键问题&#xff1a;如何有效降低企业云服务成本&#xff0c;同时…

【管理工具】CMAK安装和使用(kafka-manager)

文章目录 前言一、安装和启动1.1 安装CMAK1.2 启动cmak 二、使用CMAK2.1 添加kafka集群2.2 topic 概述2.3 broker概述2.4 其他操作 前言 一、安装和启动 1.1 安装CMAK Java环境&#xff1a;需要jdk11 $ java -version java version "11.0.5" 2019-10-15 LTS Java…

Maven3.9.1安装及环境变量配置

一、Maven的下载与安装 maven各版本下载地址 打开链接后自行选择对应版本 下载完成后解压安装,最好别选择c盘,安装目录路径等使用英文,避免产生其他问题 我这里选择的是D盘 二、Maven的环境变量配置 2.1、右键点击此电脑选择属性&#xff0c;点击高级系统设置&#xff0c;点…

Python之字符串、正则表达式练习

目录 1、输出随机字符串2、货币的转换&#xff08;字符串 crr107&#xff09;3、凯撒加密&#xff08;book 实验 19&#xff09;4、字符替换5、检测字母或数字6、纠正字母7、输出英文中所有长度为3个字母的单词 1、输出随机字符串 编写程序&#xff0c;输出由英文字母大小写或…

现一个智能的SQL编辑器

补给资料 管注公众号&#xff1a;码农补给站 前言 目前我司的多个产品中都支持在线编辑 SQL 来生成对应的任务。为了优化用户体验&#xff0c;在使用 MonacoEditor 为编辑器的基础上&#xff0c;我们还支持了如下几个重要功能&#xff1a; 多种 SQL 的语法高亮多种 S…

订水商城实战教程08-轮播图

首页我们已经开发了店铺信息展示以及搜索功能&#xff0c;接着需要展示轮播图的功能。轮播图需要存放在数据源中&#xff0c;点击图片的时候要访问公众号的文章。 1 创建数据源 先创建数据源用来存放轮播图&#xff0c;打开控制台&#xff0c;点击数据模型&#xff0c;点击号…

sqlite3.NotSupportedError: deterministic=True requires SQLite 3.8.3 or higher

问题描述 sqlite3.NotSupportedError: deterministicTrue requires SQLite 3.8.3 or higher 解决方法 A kind of solution is changing the database from sqlite3 to pysqlite3. After acticate the virtualenv, install pysqlite. pip3 install pysqlite3 pip3 install …

网工内推 | 上市公司,云平台运维,IP认证优先,13薪

01 上海新炬网络信息技术股份有限公司 招聘岗位&#xff1a;云平台运维工程师 职责描述&#xff1a; 1、负责云平台运维&#xff0c;包括例行巡检、版本发布、问题及故障处理、平台重保等&#xff0c;保障平台全年稳定运行&#xff1b; 2、参与制定运维标准规范与流程&#x…