基于SpringBoot、Elasticsearch实现酒店查询功能!

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 在一些应用中,Elasticsearch应用于全文搜索的很少,多是用于ToC端的查询,更像是一个缓存数据库。

前言

在一些应用中,Elasticsearch应用于全文搜索的很少,多是用于ToC端的查询,更像是一个缓存数据库。

与ToB的查询项是确定的不同——例如查名字,性别,地址,直接去DB对应的字段查就可以了,ToC大多是一个搜索框,对应多个查询项,如图:

这时候用DB就显得很不优雅了,用Elasticsearch就比较好了。

本文内容主要是通过基于SpringBoot、Elasticsearch实现对酒店查询的功能,列出一些常用Elasticsearch的API。

功能有:

1、在Elasticsearch上创建hotel索引,并配置映射。

2、从MySQL批量导入酒店信息至Elasticsearch。

3、添加单条酒店信息至MySQL、Elasticsearch。

4、根据关键词从Elasticsearch查询酒店列表。

5、根据坐标从Elasticsearch查询酒店列表。

6、根据价格范围从Elasticsearch查询酒店列表。

注:因为主要目的是展示常用的API,所以在设计上没有优化,例如数据库表设计上有一些不合理的,price不应出现在酒店表里;代码上没有优化,例如分页、自定义排序等就直接写死在代码里了;Elasticsearch也没有配置完全,分词器没有使用常用的IK。

关注公众号:麒麟改bug,一起探讨Java技术交流,获取核心学习笔记

代码&讲述

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.0</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.leo</groupId>
    <artifactId>hotel-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hotel-server</name>
    <description>酒店-MySQL-ES</description>

    <properties>
        <java.version>1.8</java.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.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>29.0-jre</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.properties

server.servlet.context-path=/hotel
server.port=8080
#AOP
spring.aop.proxy-target-class=true

#JDBC
spring.datasource.name=mall
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mall?useUnicode=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#指定XML文件目录
mybatis.mapper-locations=classpath:mapper/*.xml
#开启下划线与驼峰的转换
mybatis.configuration.map-underscore-to-camel-case=true

建表语句

CREATE TABLE `t_hotel` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `hotel_name` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '酒店名称',
  `province` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '省',
  `city` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '市',
  `area` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '区',
  `location` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '经纬度',
  `landmark` varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '地标',
  `label` varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '标签',
  `price` int(11) NOT NULL DEFAULT '0' COMMENT '价格',
  `available_flag` tinyint(4) NOT NULL DEFAULT '2' COMMENT '营业标识。1营业2歇业',
  `hotel_desc` varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '描述',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '开店时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='酒店表';

仅做展示用,缺失一些字段,也有一些不合理的字段。

实体类&VO

省略get/set

public class HotelEntity implements Serializable {
    private static final long serialVersionUID = 1980059323208910883L;

    /**
     * id
     */
    private Integer id;

    /**
     * 酒店名称
     */
    private String hotelName;

    /**
     * 省
     */
    private String province;
    /**
     * 市
     */
    private String city;
    /**
     * 区
     */
    private String area;

    /**
     * 经纬度
     */
    private String location;

    /**
     * 地标
     */
    private String landmark;

    /**
     * 标签
     */
    private String label;

    /**
     * 价格
     */
    private Integer price;

    /**
     * 营业标识。1营业2歇业
     */
    private Integer availableFlag;

    /**
     * 描述
     */
    private String hotelDesc;

    /**
     * 开店时间
     */
    private Date createTime;
}
public class GeoLocation implements Serializable {
    private static final long serialVersionUID = 8940851639489109853L;
    private double lat;
    private double lon;
}
public class HotelESVO implements Serializable {
    private static final long serialVersionUID = -2334463717030263164L;

    /**
     * id
     */
    private Integer id;

    /**
     * 酒店名称
     */
    private String hotelName;

    /**
     * 省
     */
    private String province;
    /**
     * 市
     */
    private String city;
    /**
     * 区
     */
    private String area;

    /**
     * 经纬度
     */
    private GeoLocation location;

    /**
     * 地标
     */
    private String landmark;

    /**
     * 标签
     */
    private String label;

    /**
     * 价格
     */
    private Integer price;

    /**
     * 营业标识。1营业2歇业
     */
    private Integer availableFlag;

    /**
     * 描述
     */
    private String hotelDesc;

    /**
     * 开店时间
     */
    private String createTime;

    /**
     * 查询关键词
     */
    private String searchKeywords;
}

HotelESVO与HotelEntity有些不同:

1、经纬度变成了GeoLocation类。

2、多了searchKeywords,供搜索用。

说一下为什么加了这个字段,用户搜索时,一般就是搜酒店名称、省区市、地标(王府井、春熙路、锦里等)、标签(网红打卡、场站接送等),全文去搜反而不如将这些关键词统一放在一起,只搜这一个字段。

3、时间从Date变成String,因为Elasticsearch不认Date

Hotel索引映射

{
    "properties": {
        "id": {
            "type": "integer"
        },
        "hotelName": {
            "type": "keyword"
        },
        "province": {
            "type": "keyword"
        },
        "city": {
            "type": "keyword"
        },
        "area": {
            "type": "keyword"
        },
        "location": {
            "type": "geo_shape"
        },
        "landmark": {
            "type": "keyword"
        },
        "label": {
            "type": "keyword"
        },
        "price": {
            "type": "integer"
        },
        "availableFlag": {
            "type": "integer"
        },
        "hotelDesc": {
            "type": "text",
            "index": "false"
        },
        "searchKeywords": {
            "type": "text",
            "analyzer": "whitespace"
        },
        "createTime": {
            "type": "date",
            "format": "yyyy-MM-dd HH:mm:ss"
        }
    }
}

有几个地方要注意:

1、为了演示方便,searchKeywords使用的分词器是空格分词器,没用IK。

2、一些字段没必要进行索引,例如hotelDesc的索引我就给禁了。

3、经纬度的映射是geo\_shape。

4、日期时间要配置格式化。

RestClientConfig

@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo("127.0.0.1:9200")
                .build();

        return RestClients.create(clientConfiguration).rest();
    }

}

SpringBoot中,原来有一个ElasticsearchTemplate可以与Elasticsearch交互,但是现在被废弃了,现在应该使用Java High Level REST Client。

跟数据库交互的Mapper、Service就不列出来了。

Controller的结构

@RestController
public class HotelController {
    private static final Logger logger = LoggerFactory.getLogger(HotelController.class);
    @Autowired
    private HotelService hotelService;
    @Autowired
    RestHighLevelClient highLevelClient;

    private HotelESVO buildVoFromEntity(HotelEntity hotelEntity) {
        // 可用复制工具
        HotelESVO vo = new HotelESVO();
        vo.setArea(hotelEntity.getArea());
        vo.setAvailableFlag(hotelEntity.getAvailableFlag());
        vo.setCity(hotelEntity.getCity());
        vo.setHotelDesc(hotelEntity.getHotelDesc());
        vo.setHotelName(hotelEntity.getHotelName());
        vo.setId(hotelEntity.getId());
        vo.setLabel(hotelEntity.getLabel());
        vo.setLandmark(hotelEntity.getLandmark());
        vo.setPrice(hotelEntity.getPrice());
        vo.setProvince(hotelEntity.getProvince());
        // 处理时间
        vo.setCreateTime(LocalDateTime.fromDateFields(hotelEntity.getCreateTime()).toString("yyyy-MM-dd HH:mm:ss"));
        // 处理坐标
        GeoLocation location = new GeoLocation();
        location.setLat(Double.valueOf(hotelEntity.getLocation().split(",")[1]));
        location.setLon(Double.valueOf(hotelEntity.getLocation().split(",")[0]));
        vo.setLocation(location);
        // 处理查询关键词 用set去重一下
        String[] labelArr = hotelEntity.getLabel().split(",");
        String[] landMarkArr = hotelEntity.getLandmark().split(",");

        Set<String> skw = Sets.newHashSet();
        skw.addAll(Arrays.asList(labelArr));
        skw.addAll(Arrays.asList(landMarkArr));
        skw.add(hotelEntity.getProvince());
        skw.add(hotelEntity.getArea());
        skw.add(hotelEntity.getCity());
        skw.add(hotelEntity.getHotelName());

        String searchKeywords = Joiner.on(" ").skipNulls().join(skw);
        vo.setSearchKeywords(searchKeywords);
        return vo;
    }
}

私有方法是Entity转VO。

后续的方法都写在Controller里面,实际工作中,要看公司的规范要求,选择合适的地方。

添加索引

@GetMapping("/addHotelIndex")
    @ResponseBody
    public CreateIndexResponse addHotelIndex() throws IOException {
        CreateIndexRequest req = new CreateIndexRequest("hotel");
        req.settings(Settings.builder().put("index.number_of_shards", 1).put("index.number_of_replicas", 1));
        req.mapping(
                "{\n" + "    \"properties\": {\n" + "        \"id\": {\n" + "            \"type\": \"integer\"\n"
                        + "        },\n" + "        \"hotelName\": {\n" + "            \"type\": \"keyword\"\n"
                        + "        },\n" + "        \"province\": {\n" + "            \"type\": \"keyword\"\n"
                        + "        },\n" + "        \"city\": {\n" + "            \"type\": \"keyword\"\n"
                        + "        },\n" + "        \"area\": {\n" + "            \"type\": \"keyword\"\n"
                        + "        },\n" + "        \"location\": {\n" + "            \"type\": \"geo_point\"\n"
                        + "        },\n" + "        \"landmark\": {\n" + "            \"type\": \"keyword\"\n"
                        + "        },\n" + "        \"label\": {\n" + "            \"type\": \"keyword\"\n"
                        + "        },\n" + "        \"price\": {\n" + "            \"type\": \"integer\"\n"
                        + "        },\n" + "        \"availableFlag\": {\n" + "            \"type\": \"integer\"\n"
                        + "        },\n" + "        \"hotelDesc\": {\n" + "            \"type\": \"text\",\n"
                        + "            \"index\": \"false\"\n" + "        },\n" + "        \"searchKeywords\": {\n"
                        + "            \"type\": \"text\",\n" + "            \"analyzer\": \"whitespace\"\n"
                        + "        },\n" + "        \"createTime\": {\n" + "            \"type\": \"date\",\n"
                        + "            \"format\": \"yyyy-MM-dd HH:mm:ss\"\n" + "        }\n" + "    }\n" + "}",
                XContentType.JSON);
        CreateIndexResponse createIndexResponse = highLevelClient.indices().create(req, RequestOptions.DEFAULT);
        return createIndexResponse;
    }

一般来说,在Elasticsearch上创建索引就像在MySQL上创建表,应该是执行脚本或者使用Kibana,本文就是想展示一下相关API,才放在代码里了。

将数据库里的数据导入ES

@GetMapping("/importHotel2ES")
    @ResponseBody
    public BulkResponse importHotel2ES() throws IOException {
        // 为防止数据过大,可以批量获取
        List<HotelEntity> hotels = hotelService.findAll();
        BulkRequest bulkReq = new BulkRequest("hotel");
        Gson gson = new Gson();
        for (HotelEntity hotelEntity : hotels) {
            HotelESVO vo = this.buildVoFromEntity(hotelEntity);
            IndexRequest req = new IndexRequest();
            req.id(hotelEntity.getId().toString());
            req.source(gson.toJson(vo), XContentType.JSON);
            bulkReq.add(req);
        }
        BulkResponse bulkRes = highLevelClient.bulk(bulkReq, RequestOptions.DEFAULT);
        return bulkRes;
    }

有可能在实际工作中,Elasticsearch是后上的,所以有个批量导入的初始化方法还是很有必要的,为防止数据量过大,应该分批导入。

这里主要是展示一下Elasticsearch的批量操作API。

添加酒店信息:

    @PostMapping("/add")
    @ResponseBody
    public HotelEntity add(@RequestBody HotelEntity entity) throws IOException {
        entity.setCreateTime(new Date());
        hotelService.add(entity);
        logger.info("保存成功:" + entity.toString());
        // 同步到ES
        Gson gson = new Gson();
        HotelESVO vo = this.buildVoFromEntity(entity);
        IndexRequest req = new IndexRequest("hotel");
        req.id(entity.getId().toString());
        req.source(gson.toJson(vo), XContentType.JSON);
        IndexResponse indexResponse = highLevelClient.index(req, RequestOptions.DEFAULT);
        logger.info("同步ES:" + indexResponse.toString());
        return entity;
    }

在实际工作中,根据业务要求,同步数据到Elasticsearch的工作可以采用上面的方法,实时性得到保障。也可以使用Elasticsearch提供的异步方法indexAsync。或者写一个定时器,每隔一段时间从数据库批量导入。

关键词查询

    @GetMapping("/search")
    @ResponseBody
    public List<HotelESVO> search(@RequestParam String keywords) throws IOException {
        SearchRequest searchRequest = new SearchRequest("hotel");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 查询 默认是OR
        sourceBuilder.query(QueryBuilders.matchQuery("searchKeywords", keywords).operator(Operator.AND));
        // 分页
        sourceBuilder.from(0);
        sourceBuilder.size(10);
        // 排序
        sourceBuilder.sort(new FieldSortBuilder("id").order(SortOrder.DESC));
        // 定制要返回的信息,隐藏的信息
        String[] includeFields = new String[] { "id", "hotelName", "province", "city", "area", "location", "landmark",
                "label", "availableFlag", "hotelDesc", "price", "createTime" };
        String[] excludeFields = new String[] { "searchKeywords" };
        sourceBuilder.fetchSource(includeFields, excludeFields);
        searchRequest.source(sourceBuilder);
        SearchResponse res = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] searchHits = res.getHits().getHits();

        Gson gson = new Gson();
        List<HotelESVO> vos = Lists.newArrayList();
        for (SearchHit hit : searchHits) {
            String sourceAsString = hit.getSourceAsString();
            vos.add(gson.fromJson(sourceAsString, HotelESVO.class));
        }
        return vos;
    }

注意QueryBuilders最后面的operator,默认是or,如果用户输入"北京 四川",只要searchKeywords包含北京或四川,都会搜索出来,如果是and,就必须同时包含北京和四川才行。

如果是or,这次搜索会把其他北京的酒店也搜索出来。实际工作中用or还是and,按照业务来。

根据经纬度搜索

范围的单位是公里,排序是由近及远。

    @GetMapping("/searchGeo")
    @ResponseBody
    public List<HotelESVO> searchGeo(@RequestParam Double lat, @RequestParam Double lon, @RequestParam Integer distance)
            throws IOException {
        SearchRequest searchRequest = new SearchRequest("hotel");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 查询
        sourceBuilder.query(
                QueryBuilders.geoDistanceQuery("location").point(lat, lon).distance(distance, DistanceUnit.KILOMETERS));
        // 分页
        sourceBuilder.from(0);
        sourceBuilder.size(10);
        // 排序
        sourceBuilder.sort(new GeoDistanceSortBuilder("location", lat, lon).order(SortOrder.DESC));
        // 定制要返回的信息,隐藏的信息
        String[] includeFields = new String[] { "id", "hotelName", "province", "city", "area", "location", "landmark",
                "label", "availableFlag", "hotelDesc", "price", "createTime" };
        String[] excludeFields = new String[] { "searchKeywords" };
        sourceBuilder.fetchSource(includeFields, excludeFields);
        searchRequest.source(sourceBuilder);
        SearchResponse res = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] searchHits = res.getHits().getHits();

        Gson gson = new Gson();
        List<HotelESVO> vos = Lists.newArrayList();
        for (SearchHit hit : searchHits) {
            String sourceAsString = hit.getSourceAsString();
            vos.add(gson.fromJson(sourceAsString, HotelESVO.class));
        }
        return vos;
    }

价格范围搜索

    @GetMapping("/searchPrice")
    @ResponseBody
    public List<HotelESVO> searchPrice(@RequestParam(required = false) Integer min,
            @RequestParam(required = false) Integer max) throws IOException {
        if (Objects.isNull(min)) {
            min = 0;
        }
        if (Objects.isNull(max)) {
            max = Integer.MAX_VALUE;
        }
        SearchRequest searchRequest = new SearchRequest("hotel");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 查询
        sourceBuilder.query(QueryBuilders.rangeQuery("price").gte(min).lte(max));
        // 分页
        sourceBuilder.from(0);
        sourceBuilder.size(10);
        // 排序
        sourceBuilder.sort(new FieldSortBuilder("price").order(SortOrder.ASC));
        // 定制要返回的信息,隐藏的信息
        String[] includeFields = new String[] { "id", "hotelName", "province", "city", "area", "location", "landmark",
                "label", "availableFlag", "hotelDesc", "price", "createTime" };
        String[] excludeFields = new String[] { "searchKeywords" };
        sourceBuilder.fetchSource(includeFields, excludeFields);
        searchRequest.source(sourceBuilder);
        SearchResponse res = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] searchHits = res.getHits().getHits();

        Gson gson = new Gson();
        List<HotelESVO> vos = Lists.newArrayList();
        for (SearchHit hit : searchHits) {
            String sourceAsString = hit.getSourceAsString();
            vos.add(gson.fromJson(sourceAsString, HotelESVO.class));
        }
        return vos;
    }
    关注公众号:麒麟改bug,一起探讨Java技术交流,获取核心学习笔记

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
2月前
|
SQL 前端开发 关系型数据库
SpringBoot使用mysql查询昨天、今天、过去一周、过去半年、过去一年数据
SpringBoot使用mysql查询昨天、今天、过去一周、过去半年、过去一年数据
72 9
|
3月前
|
JSON Java 网络架构
elasticsearch学习四:使用springboot整合 rest 进行搭建elasticsearch服务
这篇文章介绍了如何使用Spring Boot整合REST方式来搭建和操作Elasticsearch服务。
157 4
elasticsearch学习四:使用springboot整合 rest 进行搭建elasticsearch服务
|
2月前
|
JSON Java API
springboot集成ElasticSearch使用completion实现补全功能
springboot集成ElasticSearch使用completion实现补全功能
49 1
|
3月前
|
机器学习/深度学习 存储 运维
探索未来:结合机器学习功能拓展Elasticsearch应用场景
【10月更文挑战第8天】随着数据量的爆炸性增长,高效的数据存储、检索和分析变得越来越重要。Elasticsearch 作为一个分布式的搜索和分析引擎,以其强大的全文搜索能力、实时分析能力和可扩展性而闻名。近年来,随着机器学习技术的发展,将机器学习集成到 Elasticsearch 中成为了一种新的趋势,这不仅增强了 Elasticsearch 的数据分析能力,还开拓了一系列新的应用场景。
87 7
|
3月前
|
Web App开发 JavaScript Java
elasticsearch学习五:springboot整合 rest 操作elasticsearch的 实际案例操作,编写搜索的前后端,爬取京东数据到elasticsearch中。
这篇文章是关于如何使用Spring Boot整合Elasticsearch,并通过REST客户端操作Elasticsearch,实现一个简单的搜索前后端,以及如何爬取京东数据到Elasticsearch的案例教程。
260 0
elasticsearch学习五:springboot整合 rest 操作elasticsearch的 实际案例操作,编写搜索的前后端,爬取京东数据到elasticsearch中。
|
3月前
|
自然语言处理 Java Maven
elasticsearch学习二:使用springboot整合TransportClient 进行搭建elasticsearch服务
这篇博客介绍了如何使用Spring Boot整合TransportClient搭建Elasticsearch服务,包括项目创建、Maven依赖、业务代码和测试示例。
152 0
elasticsearch学习二:使用springboot整合TransportClient 进行搭建elasticsearch服务
|
3月前
|
自然语言处理 搜索推荐 Java
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(一)
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图
70 0
|
2月前
|
存储 安全 数据管理
如何在 Rocky Linux 8 上安装和配置 Elasticsearch
本文详细介绍了在 Rocky Linux 8 上安装和配置 Elasticsearch 的步骤,包括添加仓库、安装 Elasticsearch、配置文件修改、设置内存和文件描述符、启动和验证 Elasticsearch,以及常见问题的解决方法。通过这些步骤,你可以快速搭建起这个强大的分布式搜索和分析引擎。
69 5
|
3月前
|
存储 JSON Java
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
这篇文章是关于Elasticsearch的学习指南,包括了解Elasticsearch、版本对应、安装运行Elasticsearch和Kibana、安装head插件和elasticsearch-ik分词器的步骤。
291 0
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
|
4月前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo