it编程 > 前端脚本 > Erlang

Elasticsearch的使用教程

156人参与 2024-08-02 Erlang

elasticsearch简介

elasticsearch 是一个分布式、restful 风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例。作为 elastic stack 的核心,elasticsearch 会集中存储您的数据,让您飞快完成搜索,微调相关性,进行强大的分析,并轻松缩放规模。

elasticsearch的安装

下载安装包

下载elasticsearch7.17.3版本的zip包,并解压到指定目录,下载地址:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-7-17-3
在这里插入图片描述

安装中文分词器

安装中文分词器,注意下载与elasticsearch对应的版本,下载地址
https://github.com/medcl/elasticsearch-analysis-ik/releases

下载完成后解压

下载完成后解压到elasticsearch的plugins目录下
在这里插入图片描述
运行bin目录下的elasticsearch.bat启动elasticsearch服务。
在这里插入图片描述
访问 http://localhost:9200/ 出现这个界面,表示启动成功
在这里插入图片描述

安装kibana

作为elasticsearch 的客户端访问
下载kibana,作为访问elasticsearch的客户端,请下载7.17.3版本的zip包,并解压到指定目录,下载地址:https://www.elastic.co/cn/downloads/past-releases/kibana-7-17-3
在这里插入图片描述

运行bin目录下的kibana.bat,启动kibana服务;
打开kibana的用户界面,访问地址:http://localhost:5601
在这里插入图片描述

相关概念

● near realtime(近实时):elasticsearch是一个近乎实时的搜索平台,这意味着从索引文档到可搜索文档之间只有一个轻微的延迟(通常是一秒钟)。
● cluster(集群):群集是一个或多个节点的集合,它们一起保存整个数据,并提供跨所有节点的联合索引和搜索功能。每个集群都有自己的唯一集群名称,节点通过名称加入集群。
● node(节点):节点是指属于集群的单个elasticsearch实例,存储数据并参与集群的索引和搜索功能。可以将节点配置为按集群名称加入特定集群,默认情况下,每个节点都设置为加入一个名为elasticsearch的群集。
● index(索引):索引是一些具有相似特征的文档集合,类似于mysql中数据库的概念。
● type(类型):类型是索引的逻辑类别分区,通常,为具有一组公共字段的文档类型,类似mysql中表的概念。注意:在elasticsearch 6.0.0及更高的版本中,一个索引只能包含一个类型。
● document(文档):文档是可被索引的基本信息单位,以json形式表示,类似于mysql中行记录的概念。
● shards(分片):当索引存储大量数据时,可能会超出单个节点的硬件限制,为了解决这个问题,elasticsearch提供了将索引细分为分片的概念。分片机制赋予了索引水平扩容的能力、并允许跨分片分发和并行化操作,从而提高性能和吞吐量。
● replicas(副本):在可能出现故障的网络环境中,需要有一个故障切换机制,elasticsearch提供了将索引的分片复制为一个或多个副本的功能,副本在某些节点失效的情况下提供高可用性。

简单操作

通过kibana的dev tools功能,我们可以操作elasticsearch;
在这里插入图片描述

索引操作

创建索引并查看

put /customer
get /_cat/indices?v

在这里插入图片描述
删除索引并查看

delete /customer
get /_cat/indices?v

类型操作

首先要导入一批数据

 https://github.com/macrozheng/mall-learning/blob/teach/document/json/accounts.json 
post /bank/account/_bulk

查看文档类型的操作

get /bank/_mapping

在索引中添加文档

put /customer/doc/1
{
  "name": "john doe"
}

查看索引中的文档

get /customer/doc/1

修改索引中的文档

post /customer/doc/1/_update
{
  "doc": { "name": "jane doe" }
}

删除索引中的文档

delete /customer/doc/1

数据搜索

查询表达式(query dsl)是一种非常灵活又富有表现力的查询语言,elasticsearch使用它可以以简单的json接口来实现丰富的搜索功能,下面的搜索操作都将使用它。

数据导入

首先要导入一批数据

 https://github.com/macrozheng/mall-learning/blob/teach/document/json/accounts.json 
post /bank/account/_bulk

搜索入门

最简单的搜索,使用match_all来表示,例如搜索全部

get /bank/_search
{
  "query": { "match_all": {} }
}

在这里插入图片描述

分页搜索,from表示偏移量,从0开始,size表示每页显示的数量

get /bank/_search
{
  "query": { "match_all": {} },
  "from": 0,
  "size": 10
}

搜索排序,使用sort表示,例如按balance字段降序排列;

get /bank/_search
{
  "query": { "match_all": {} },
  "sort": { "balance": { "order": "desc" } }
}

搜索并返回指定字段内容,使用_source表示,例如只返回account_number和balance两个字段内容:

get /bank/_search
{
  "query": { "match_all": {} },
  "_source": ["account_number", "balance"]
}

条件搜索

条件搜索,使用match表示匹配条件,例如搜索出account_number为20的文档

get /bank/_search
{
  "query": {
    "match": {
      "account_number": 20
    }
  }
}

短语匹配搜索,使用match_phrase表示,例如搜索address字段中同时包含mill和lane的文档:

get /bank/_search
{
  "query": {
    "match_phrase": {
      "address": "mill lane"
    }
  }
}

组合搜索

组合搜索,使用bool来进行组合,must表示同时满足,例如搜索address字段中同时包含mill和lane的文档;

get /bank/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}

组合搜索,should表示满足其中任意一个,搜索address字段中包含mill或者lane的文档;

get /bank/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}

组合搜索,must_not表示同时不满足,例如搜索address字段中不包含mill且不包含lane的文档;

get /bank/_search
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}

组合搜索,组合must和must_not,例如搜索age字段等于40且state字段不包含id的文档;

get /bank/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "age": "40" } }
      ],
      "must_not": [
        { "match": { "state": "id" } }
      ]
    }
  }
}

过滤搜索

搜索过滤,使用filter来表示,例如过滤出balance字段在20000~30000的文档;

get /bank/_search
{
  "query": {
    "bool": {
      "must": { "match_all": {} },
      "filter": {
        "range": {
          "balance": {
            "gte": 20000,
            "lte": 30000
          }
        }
      }
    }
  }
}

参考资料https://www.elastic.co/guide/en/elasticsearch/reference/7.17/getting-started.html

spring data elasticsearch

spring data elasticsearch是spring提供的一种以spring data风格来操作数据存储的方式,它可以避免编写大量的样板代码。

常用注解

在这里插入图片描述
其中常用的fieldtype类型有如下几种:

public enum fieldtype {
	auto("auto"), //自动判断字段类型
	text("text"), //会进行分词并建了索引的字符类型
	keyword("keyword"), //不会进行分词建立索引的类型
	long("long"), //
	integer("integer"), //
	short("short"), //
	byte("byte"), //
	double("double"), //
	float("float"), //
	date("date"), //
	boolean("boolean"), //
	object("object"), //
	nested("nested"), //嵌套对象类型
	ip("ip"), //
}

springdata 方式的数据操作

可以使用衍生查询,在接口中直接指定查询方法名称便可查询,无需进行实现,如商品表中有商品名称、标题和关键字,直接定义以下查询,就可以对这三个字段进行全文搜索。

/**
 * @description 商品es操作类
 */
public interface esproductrepository extends elasticsearchrepository<esproduct, long> {
    /**
     * 搜索查询
     *
     * @param name              商品名称
     * @param subtitle          商品标题
     * @param keywords          商品关键字
     * @param page              分页信息
     * @return
     */
    page<esproduct> findbynameorsubtitleorkeywords(string name, string subtitle, string keywords, pageable page);
}

通过@query注解可以使用elasticsearch的原生dsl语句进行查询;

/**
 * @description 商品es操作类
 */
public interface esproductrepository extends elasticsearchrepository<esproduct, long> {
    @query("{"bool" : {"must" : {"field" : {"name" : " ? 0"}}}}")
    page<esproduct> findbyname(string name, pageable pageable);
}

整合elasticsearch商品搜索

整理依赖配置

<!--elasticsearch相关依赖-->
<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-data-elasticsearch</artifactid>
</dependency>
spring:
  data:
    elasticsearch:
      repositories:
        enabled: true # 开启es仓库配置,自动为仓库接口生成实现类
  elasticsearch:
    uris: http://localhost:9200 # es的连接地址及端口号

实现商品搜索功能

添加商品文档对象esproduct

不需要中文分词的字段设置成keyword类型,需要中文分词的设置成text类型,并设置分词器为ik_max_word;

/**
 * @description 搜索商品的信息
 */
@data
@equalsandhashcode
@document(indexname = "pms")
@setting(shards = 1,replicas = 0)
public class esproduct implements serializable {
    private static final long serialversionuid = -1l;
    @id
    private long id;
    @field(type = fieldtype.keyword)
    private string productsn;
    private long brandid;
    @field(type = fieldtype.keyword)
    private string brandname;
    private long productcategoryid;
    @field(type = fieldtype.keyword)
    private string productcategoryname;
    private string pic;
    @field(analyzer = "ik_max_word",type = fieldtype.text)
    private string name;
    @field(analyzer = "ik_max_word",type = fieldtype.text)
    private string subtitle;
    @field(analyzer = "ik_max_word",type = fieldtype.text)
    private string keywords;
    private bigdecimal price;
    private integer sale;
    private integer newstatus;
    private integer recommandstatus;
    private integer stock;
    private integer promotiontype;
    private integer sort;
    @field(type =fieldtype.nested)
    private list<esproductattributevalue> attrvaluelist;
}

继承elasticsearchrepository接口

这样就拥有了一些基本的elasticsearch数据操作方法,同时定义了一个衍生查询方法;

/**

 * @description 商品es操作类

 */
public interface esproductrepository extends elasticsearchrepository<esproduct, long> {
    /**
     * 搜索查询
     *
     * @param name              商品名称
     * @param subtitle          商品标题
     * @param keywords          商品关键字
     * @param page              分页信息
     * @return
     */
    page<esproduct> findbynameorsubtitleorkeywords(string name, string subtitle, string keywords, pageable page);

}

添加esproductservice,定义好es的操作方法

/**
 * @description 商品搜索管理service
 */
public interface esproductservice {
    /**
     * 从数据库中导入所有商品到es
     */
    int importall();

    /**
     * 根据id删除商品
     */
    void delete(long id);

    /**
     * 根据id创建商品
     */
    esproduct create(long id);

    /**
     * 批量删除商品
     */
    void delete(list<long> ids);

    /**
     * 根据关键字搜索名称或者副标题
     */
    page<esproduct> search(string keyword, integer pagenum, integer pagesize);

}

添加esproductservice接口的实现类esproductserviceimpl;

/**
 * @description 搜索商品管理service实现类
 */
@service
public class esproductserviceimpl implements esproductservice {
    private static final logger logger = loggerfactory.getlogger(esproductserviceimpl.class);
    @autowired
    private esproductdao productdao;
    @autowired
    private esproductrepository productrepository;
    @override
    public int importall() {
        list<esproduct> esproductlist = productdao.getallesproductlist(null);
        iterable<esproduct> esproductiterable = productrepository.saveall(esproductlist);
        iterator<esproduct> iterator = esproductiterable.iterator();
        int result = 0;
        while (iterator.hasnext()) {
            result++;
            iterator.next();
        }
        return result;
    }

    @override
    public void delete(long id) {
        productrepository.deletebyid(id);
    }

    @override
    public esproduct create(long id) {
        esproduct result = null;
        list<esproduct> esproductlist = productdao.getallesproductlist(id);
        if (esproductlist.size() > 0) {
            esproduct esproduct = esproductlist.get(0);
            result = productrepository.save(esproduct);
        }
        return result;
    }

    @override
    public void delete(list<long> ids) {
        if (!collectionutils.isempty(ids)) {
            list<esproduct> esproductlist = new arraylist<>();
            for (long id : ids) {
                esproduct esproduct = new esproduct();
                esproduct.setid(id);
                esproductlist.add(esproduct);
            }
            productrepository.deleteall(esproductlist);
        }
    }

    @override
    public page<esproduct> search(string keyword, integer pagenum, integer pagesize) {
        pageable pageable = pagerequest.of(pagenum, pagesize);
        return productrepository.findbynameorsubtitleorkeywords(keyword, keyword, keyword, pageable);
    }

}

添加esproductcontroller定义接口。

/**
 * @description 搜索商品管理controller

 */
@controller
@api(tags = "esproductcontroller")
@tag(name = "esproductcontroller", description = "搜索商品管理")
@requestmapping("/esproduct")
public class esproductcontroller {
    @autowired
    private esproductservice esproductservice;

    @apioperation(value = "导入所有数据库中商品到es")
    @requestmapping(value = "/importall", method = requestmethod.post)
    @responsebody
    public commonresult<integer> importalllist() {
        int count = esproductservice.importall();
        return commonresult.success(count);
    }

    @apioperation(value = "根据id删除商品")
    @requestmapping(value = "/delete/{id}", method = requestmethod.get)
    @responsebody
    public commonresult<object> delete(@pathvariable long id) {
        esproductservice.delete(id);
        return commonresult.success(null);
    }

    @apioperation(value = "根据id批量删除商品")
    @requestmapping(value = "/delete/batch", method = requestmethod.post)
    @responsebody
    public commonresult<object> delete(@requestparam("ids") list<long> ids) {
        esproductservice.delete(ids);
        return commonresult.success(null);
    }

    @apioperation(value = "根据id创建商品")
    @requestmapping(value = "/create/{id}", method = requestmethod.post)
    @responsebody
    public commonresult<esproduct> create(@pathvariable long id) {
        esproduct esproduct = esproductservice.create(id);
        if (esproduct != null) {
            return commonresult.success(esproduct);
        } else {
            return commonresult.failed();
        }
    }

    @apioperation(value = "简单搜索")
    @requestmapping(value = "/search/simple", method = requestmethod.get)
    @responsebody
    public commonresult<commonpage<esproduct>> search(@requestparam(required = false) string keyword,
                                                      @requestparam(required = false, defaultvalue = "0") integer pagenum,
                                                      @requestparam(required = false, defaultvalue = "5") integer pagesize) {
        page<esproduct> esproductpage = esproductservice.search(keyword, pagenum, pagesize);
        return commonresult.success(commonpage.restpage(esproductpage));
    }
}
(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

关于rabbitmq(docker)部署,启动,访问,连接一系列问题最全面解决办法与思路,rabbitmq报私密连接,user can only log in via localhost,页面访问失败

08-01

消息队列-RabbitMQ

08-01

Erlang、RabbitMQ下载与安装教程(windows超详细)

08-01

RabbitMQ 安装&体验

08-01

windows安装rabbitmq和环境erlang(最详细版,包括对应关系,安装错误解决方法)_erlang和rabbitmq关系

08-01

RabbitMQ3.13.x之二_RabbitMQ所有端口说明及开启后台管理功能

08-04

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论