ElasticSearch搜索引擎✧完结

ES搜索引擎



一、Kibana

一款开源的数据分析和可视化平台,此处不做主要介绍


二、IK Analysis 中文分词器

  • Es的常用插件之一
  • IK Analysis插件将Lucene IK分析器集成到elasticsearch中,支持自定义词典。
1、单机配置

官网下载地址


① 安装配置

直接上传资源到linux,解压指定位置,并进行授权

# 创建ik目录
mkdir -p /usr/local/elasticsearch/es1/elasticsearch-7.4.2/plugins/ik 
# 解压至ik目录 
unzip elasticsearch-analysis-ik-7.4.2.zip -d /usr/local/elasticsearch/es1/elasticsearch-7.4.2/plugins/ik/
#授权个es账户
chown -Rf es:es /usr/local/elasticsearch/ 

在这里插入图片描述
重启ES,测试


② 测试

直接创建索引库和设置mapping

# 创建索引库
curl -X PUT http://localhost:9200/ik -H 'Content-Type:application/json' - d'{
	"settings": { 
		"number_of_shards": 5, 
		"number_of_replicas": 1 
}
}'

# 设置mapping
# Analyzer分词配置解释:
#ik_smart:粗粒度分词,比如中华人民共和国国歌,会拆分为中华人民共和国,国歌;
#ik_max_word:细粒度分词,比如中华人民共和国国歌,会拆分为中华人民共和国,中华
#人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌,会穷
#尽各种可能的组合。

在这里插入图片描述


插入数据

curl -XPOST http://localhost:9200/ik/_create/1 -H 'Content- Type:application/json' -d' {"content":"美国留给伊拉克的是个烂摊子吗"} '
curl -XPOST http://localhost:9200/ik/_create/2 -H 'Content- Type:application/json' -d' {"content":"公安部:各地校车将享最高路权"} '
curl -XPOST http://localhost:9200/ik/_create/3 -H 'Content- Type:application/json' -d' {"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"} '
curl -XPOST http://localhost:9200/ik/_create/4 -H 'Content- Type:application/json' -d' {"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"} '

启动Es(启动es要切换到es用户下)和head客户端查看结果:
这里看出,es自动加载了插件ik
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


进行数据索引查询
在这里插入图片描述
在这里插入图片描述


三、Elasticsearch导入MySQL数据

1、安装Mysql⭐

本文使用5.7.2X版本,如果找不到对应的版本信息,可以通过该地址获取: 下载(es可以说是一个非关系型数据库)


在这里插入图片描述
安装

yum -y install mysql57-community-release-el7.rpm 
yum -y install mysql-community-server
#如果报错则更新wget
yum -y install wget
#启动查看服务器状态
systemctl start mysqld
systemctl status mysqld

这种安装方式会将MySQL添加至环境变量和启动服务

在这里插入图片描述
如果安装后启动失败:

#查看是否安装过数据库
rpm -qa|grep mysql
#删除以前安装的数据库
rpm -e 数据库文件名
#查看数据库安装后的目录
find / -name mysql 
find / -name mysqld
#在重新安装

2、修改密码和配置

修改密码并授权

#获取安装后提供的密码
grep "password" /var/log/mysqld.log
#登录数据库
mysql -u root –p
#修改密码规则
set global validate_password_policy=0; 
set global validate_password_length=4;
#修改密码
set password = password('root');
#退出重新进入

授权

# 改表法 
# 选择数据库 
use mysql; 
# 最后授权MySQL,允许远程用户登录访问
MySQL update user set host = '%' where user = 'root'; 
# 刷新权限 
flush privileges; 
# 授权法
# 允许192.168.10.105(linuxIP地址)连接访问所有库的所有表(*.*),连接密码为1234
GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.10.105' IDENTIFIED BY '1234' WITH GRANT OPTION; 
# 允许所有连接访问所有库的所有表(*.*),连接密码为1234 
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '1234' WITH GRANT OPTION; 
# 刷新权限 
FLUSH PRIVILEGES;
#关闭防火墙
systemctl stop firewalld
#查看防火墙状态
systemctl status firewalld

一定要设置防火墙,否则windons客户端无法访问


3、数据库忘记密码

忘记密码的修改方法

# 展示所有数据库
show databases; 
# 选择数据库 
use mysql; 
# 展示所有表 
show tables;
# 忘记密码后修改密码
# 第一步的作用是启动时跳过验证 
1. vi /etc/my.cnf在[mysqld]里加入skip-grant-tables 
2. 重启mysql服务,连接mysql无密码登入use mysql;选择数据库 
3. 敲下面这行代码修改密码 update mysql.user set authentication_string=password('root') where user='root';
4. vi /etc/my.cnf在[mysqld]里删除skip-grant-tables 重启mysql服务,新密码登录即可

在这里插入图片描述


4、安装Logstash

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到您最喜欢的 “存储库” 中,Logstash技术,导入数据,实现数据录入,数据处理管道。下载地址


① 安装与测试

直接安装

#创建安装目录
mkdir -p /usr/local/logstash 
#解压
tar -zxvf logstash-7.4.2.tar.gz -C /usr/local/logstash/

在这里插入图片描述


安装

cd /usr/local/logstash/logstash-7.4.2 
bin/logstash -e 'input { stdin {} } output { stdout {} }'

成功运行输入helloworld返回一个helloworld就成功了

在这里插入图片描述

在这里插入图片描述


② 同步mysql数据

上传一个驱动jar,和两个配置文件jdbc.conf,jdbc.sql

#注意:请将mysql的驱动包上传至 logstash-7.4.2/logstash-core/lib/jars/ 目录下
/usr/local/logstash/logstash-7.4.2/logstash-core/lib/jars/
# jdbc.conf
# cd /usr/local/logstash/logstash-7.4.2 
# vim jdbc.conf
    jdbc {
      # 配置数据库信息
      jdbc_connection_string => "jdbc:mysql://192.168.168.129:3306/shop?useUnicode=true&cha
racterEncoding=UTF-8&useSSL=false"      jdbc_driver_class => "com.mysql.jdbc.Driver"
      jdbc_user => "root"
      jdbc_password => "1234"
      jdbc_paging_enabled => "true"
      jdbc_page_size => "50000"
      # 执行 sql 语句文件
      statement_filepath => "/usr/local/logstash/logstash-7.4.2/jdbc.sql"
      # 定时字段 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新
      schedule => "* * * * *"
      # 是否将 sql 中 column 名称转小写
      lowercase_column_names => false
    }
}
output {
    elasticsearch {
        hosts => ["192.168.168.129:9200"]
        index => "shop"
        # 文档_id,%{goods_id}意思是取查询出来的goods_id的值,并将其映射到es的_id字段中
        # 文档_id,%{goodsId}如果是别名,意思是取查询出来的goodsId的值,并将其映射到es的_id
字段中        document_id => "%{goodsId}"
    }
    stdout {
        codec => json_lines
    }
}
--------------------------------------------------------------
# jdbc.sql
SELECT
  goods_id goodsId,
  goods_name goodsName,
  market_price marketPrice,
  original_img originalImg
FROM
  t_goods
# 检测配置文件是否编写正确
bin/logstash -f /usr/local/logstash/logstash-7.4.2/jdbc.conf -t

在这里插入图片描述


③ 创建索引库shop与mapping

索引库
在这里插入图片描述
mapping:
在这里插入图片描述


# 执行数据导入(前提是数据库中shop数据库有数据)
cd /usr/local/logstash/logstash-7.4.2/ 
#配置文件回去直接调用jdbc.sql语句将查出来的数据导入到es中
bin/logstash -f /usr/local/logstash/logstash-7.4.2/jdbc.conf
#导入较慢

最终结果
在这里插入图片描述
在这里插入图片描述


查询测试:
在这里插入图片描述


四、Elasticsearch的JavaAPI

整合IDEA

1、创建项目并配置、测试

Elasticsearch有两种连接方式: transport 、 rest,ES官方建议使用 rest 方式,

  • 直接创建一个maven,java项目引入依赖
  <dependencies>
    <!-- junit 单元测试依赖 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <!-- elasticsearch 服务依赖 -->
    <dependency>
      <groupId>org.elasticsearch</groupId>
      <artifactId>elasticsearch</artifactId>
      <version>7.4.2</version>
    </dependency>
    <!-- rest-client 客户端依赖 -->
    <dependency>
      <groupId>org.elasticsearch.client</groupId>
      <artifactId>elasticsearch-rest-client</artifactId>
      <version>7.4.2</version>
    </dependency>
    <!-- rest-high-level-client 客户端依赖 -->
    <dependency>
      <groupId>org.elasticsearch.client</groupId>
      <artifactId>elasticsearch-rest-high-level-client</artifactId>
      <version>7.4.2</version>
    </dependency>
  </dependencies>

创建测试类测试:

//连接服务器
public class EsTest {

    // ES服务器IP
    private final static String HOST = "192.168.168.129";
    // ES服务器连接方式
    private final static String SCHEME = "http";
    // 初始化 ES 服务器集群
    // 参数分别为:IP,端口,连接方式(默认为http)
    private final static HttpHost[] httpHosts = {
            new HttpHost(HOST, 9200, SCHEME)
    };

    //客户端
    private RestHighLevelClient client=null;

    /*** 获取客户端 */
    @Before
    public void getConnect() {
        client = new RestHighLevelClient(RestClient.builder(httpHosts));
    }

    /*** 关闭连接 */
    @After
    public void closeConnect() {
        try {
            if (null != client)
                client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*** 查询数据 */
    @Test
    public void testRetrieve() throws IOException {
        // 指定索引库和id
        GetRequest getRequest = new GetRequest("ik", "4");
        // 执行请求
        GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
        System.out.println(getResponse.getSource());
    }

    /*** 添加数据 */
    @Test
    public void testCreate() throws IOException {
        // 准备数据
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("username", "zhangsan");
        jsonMap.put("age", 18);
        jsonMap.put("address", "sh");
        // 指定索引库和id及数据
        IndexRequest indexRequest = new IndexRequest("ik").id("5").source(jsonMap);
        //执行请求
        IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(indexResponse.toString());
    }

    /*** 修改数据 */
    @Test
    public void testUpdate() throws IOException {
        // 准备数据
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("username", "lisi"); jsonMap.put("age", 20);
        jsonMap.put("address", "bj");
        // 指定索引库和id及数据
        UpdateRequest updateRequest = new UpdateRequest("ik", "5").doc(jsonMap);
        // 执行请求
        UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(updateResponse.toString());
    }

    /*** 批量查询-分页查询-高亮查询 */
    @Test
    public void testHighlight() throws IOException {
        // 指定索引库
        SearchRequest searchRequest = new SearchRequest("shop");
        // 构建查询对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 添加分页条件,从第 0 个开始,返回 5 个
        searchSourceBuilder.from((5-1)).size(5);
        // 构建高亮对象
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        // 指定高亮字段和高亮样式
        highlightBuilder
                .field("goodsName")
                .preTags("<span style='color:red;'>")
                .postTags("</span>");
        searchSourceBuilder.highlighter(highlightBuilder);
        // 添加查询条件
        // 指定从 goodsName 字段中查询
        String key = "中国移动联通电信";
        searchSourceBuilder.query(QueryBuilders.multiMatchQuery(key, "goodsName"));
        // 执行请求
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        // 总条数
        System.out.println(searchResponse.getHits().getTotalHits().value);
        // 结果数据(如果不设置返回条数,大于十条默认只返回十条)
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            // 构建项目中所需的数据结果集
            String highlightMessage = String
                    .valueOf(hit.getHighlightFields()
                            .get("goodsName")
                            .fragments()[0]);
            Integer goodsId = Integer.valueOf((Integer) hit.getSourceAsMap().get("goodsId"));
            String goodsName = String.valueOf(hit.getSourceAsMap().get("goodsName"));
            BigDecimal marketPrice = new BigDecimal(String.valueOf(hit.getSourceAsMap().get("marketPrice")));
            String originalImg = String.valueOf(hit.getSourceAsMap().get("originalImg"));
            System.out.println("goodsId -> " + goodsId);
            System.out.println("goodsName -> " + goodsName);
            System.out.println("highlightMessage -> " + highlightMessage);
            System.out.println("marketPrice -> " + marketPrice);
            System.out.println("originalImg -> " + originalImg);
            System.out.println("----------------------------");
        }
    }
}

在这里插入图片描述


2、SpingBooot整合ES
①、创建项目并配置
  • 创建maven中java项目,引入依赖
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.0.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <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-starter-test</artifactId>
      <scope>test</scope>
      <exclusions>
        <exclusion>
          <groupId>org.junit.vintage</groupId>
          <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    
<build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
 </build>

编写dao层与pojo接收对象

//dao层提供接口
public interface GoodsInter extends ElasticsearchRepository<Goods,Integer> {
    /*更具商品名查询*/
    public List<Goods> findByGoodsName(String goodsName);
}
//-------------------------------------------------------
//pojo
@Document(indexName = "shop",shards = 5,replicas = 1,createIndex = false)
public class Goods implements Serializable {
    /*** 商品id */
    @Id
    private Integer goodsId;
    /*** 商品名称 */
    @Field(type = FieldType.Text,analyzer = "ik_max_word")
    private String goodsName;
    /*** 市场价 */
    @Field(type = FieldType.Double)
    private BigDecimal marketPrice;
    /*** 商品上传原始图 */
    @Field(type = FieldType.Keyword)
    private String originalImg;
    /*** t_goods */
    private static final long serialVersionUID = 1L;
    //此处省略构造器和toString set get方法
    
/**为需要使用索引库的实体类加上注解 @Document 部分属性如下
indexName="索引库名" shards = 分片数量(默认1) replicas = 副本数量(默认1)
为id属性 添加 @Id 注释
各个字段加上注解并制定类型 @Field 部分属性如下
type= FieldType.枚举 : 指定字段类型 Keyword不分词, Text分词 对应着
elasticsearch的字段类型
为需要分词的字段添加分词器 analyzer="分词器名" (ik分词器固定写法 ik_max_word )
是否创建索引 createIndex=boolean(默认true)**/
    

编写启动类

@SpringBootApplication
public class Start {
    public static void main(String[] args) {
        SpringApplication.run(Start.class,args);
    }
}
//测试文件目录与项目文件加目录要一直,否则扫描不到启动类,导致启动失败

②、测试

编写测试类

@SpringBootTest
public class EsTest {

    @Autowired
    GoodsInter goodsInter;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /*** 根据商品名查询 */
    @Test
    public void testFindByName() {
        List<Goods> list = goodsInter.findByGoodsName("%中国%");
        list.forEach(System.out::println);
    }
    /*** 批量插入,查询所有 */
    @Test public void testSaveAll() {
        //批量插入
        List<Goods> list = new ArrayList<>();
        list.add(new Goods(152, "测试手机1", new BigDecimal("500"), "jpg"));
        list.add(new Goods(153, "测试手机2", new BigDecimal("800"), "png"));
        goodsInter.saveAll(list);
        //查询所有
        Iterable<Goods> all = goodsInter.findAll(); all.forEach(System.out::println);
    }

    /*** 索引操作 (已经纯在)*/
    //等值收缩由局限性于是使用esTemplate的检索方法
    @Test
    public void testIndex() {
        //设置索引信息(实体类),返回indexOperations
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Goods.class);
        indexOperations.create();
        //创建索引映射
        Document mapping = indexOperations.createMapping();
        //将映射写入索引
        indexOperations.putMapping(mapping);
        //获取索引
        Map<String, Object> map = indexOperations.getMapping();
        map.forEach((k, v) -> System.out.println(k + "-->" + v));
        //索引是否存在
        boolean exists = indexOperations.exists(); System.out.println(exists);
        //删除索引
        indexOperations.delete();

    }
    /*** 增删改 */
    @Test
    public void testDocument() {
        /** 根据id和索引删除,返回删除的id
        * 第一个参数:id,String类型 * 第二个参数:索引库对象 */
        String count = elasticsearchRestTemplate.delete("150", IndexCoordinates.of("shop"));
         System.out.println(count);
         /*** 删除查询结果 * 第一个参数:查询对象 * 第二个参数:索引类字节码 * 第三个参数:索引库对象 */
         elasticsearchRestTemplate.delete( new NativeSearchQueryBuilder()
                 .withQuery(QueryBuilders.matchQuery("goodsName", "测试"))
                 .build(), Goods.class, IndexCoordinates.of("shop"));
         //新增/更新(id不存在就新增,存在就更新)
         List<Goods> list = new ArrayList<>();
         list.add(new Goods(150, "测试手机3", new BigDecimal("100"), "jpg"));
         list.add(new Goods(151, "测试手机4", new BigDecimal("200"), "png"));
         Iterable<Goods> save = elasticsearchRestTemplate.save(list);
         save.forEach(System.out::println);

    }

    /*** 匹配查询 */
    @Test
    public void testSearchMatch() {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        NativeSearchQuery query = nativeSearchQueryBuilder
                /*** 第一个参数:关键词 * 第二个参数:对应es的字段 */
                .withQuery(QueryBuilders.multiMatchQuery("中国移动联通电信", "goodsName"))
                .build(); SearchHits<Goods> search = elasticsearchRestTemplate.search(query, Goods.class);
                search.forEach(searchHit -> System.out.println(searchHit.getContent()));
    }

    /*** 分页,排序,高亮查询 */
    @Test
    public void testSearchPage() {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        NativeSearchQuery query = nativeSearchQueryBuilder
                /*** 第一个参数:关键词 * 第二个参数:对应es的字段 */
                .withQuery(QueryBuilders.multiMatchQuery("中国移动联通电 信", "goodsName"))
                /*** 第一个参数:当前页,0开始 * 第二个参数:每个条数 * 第三个参数:排序对象 * 升序/降序 * 比较字段 */
                //.withPageable(PageRequest.of(0, 5, Sort.Direction.DESC, "goodsId", "marketPrice"))
                // 分页
                .withPageable(PageRequest.of(0, 5))
                //.withSort(SortBuilders.fieldSort("marketPrice").order(SortOrder.ASC))
                //高亮,默认样式<em></em>(斜体)
                //.withHighlightFields(new HighlightBuilder.Field("goodsName"))
                //高亮,指定样式
                .withHighlightBuilder(new HighlightBuilder()
                        .field("goodsName")
                        .preTags("<span style='color:red;'>")
                        .postTags("</span>")).build();
        SearchHits<Goods> search = elasticsearchRestTemplate.search(query, Goods.class);
        for (SearchHit<Goods> searchHit : search) {
            //id
            System.out.println(searchHit.getId());
            //分数
            System.out.println(searchHit.getScore());
            //排序的值
            Double sortValues = (Double) searchHit.getSortValues().get(0);
            System.out.println(sortValues);
            //高亮信息
            String highlightMessage = searchHit.getHighlightField("goodsName").get(0);
            System.out.println(highlightMessage);
            //结果对象
            System.out.println(searchHit.getContent());
            System.out.println("----------------------------------------");
        }
    }

}

在这里插入图片描述


SpringBoot整合中,实现类接口ElasticsearchRepository,此接口为我们提供了很多方法,并且可以更具一些常用的需求组合出需要的方法,不需要我们手动去写实现方法,爆赞👍(精美壁纸一份)


在这里插入图片描述

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

每日小新

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

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

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

打赏作者

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

抵扣说明:

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

余额充值