找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

325

积分

0

好友

44

主题
发表于 6 天前 | 查看: 9| 回复: 0

Elasticsearch 是一个分布式搜索和分析引擎,对于开发者而言,它可以理解为高性能的全文搜索引擎,能够将数据转换为可快速检索的索引,支持模糊匹配、分词查询和聚合统计等功能。

核心概念解析

与关系型数据库类比可以快速理解 Elasticsearch 的基本结构:

Elasticsearch MySQL 说明
Index Database 数据集合,如"文章库"
Document Row 单条数据记录
Field Column 文档属性字段
Mapping Schema 字段类型定义
DSL查询 SQL查询 JSON格式的查询语句

这种对应关系有助于快速掌握 Elasticsearch 的数据模型设计思路。

环境部署方案

安装包部署方式

步骤1:获取安装包

# 官方下载(网络可能较慢)
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.15.1-windows-x86_64.zip

# 推荐使用国内镜像
# 华为镜像:https://mirrors.huaweicloud.com/elasticsearch/7.15.1/

步骤2:配置调整

# 解压安装包
unzip elasticsearch-7.15.1-windows-x86_64.zip
cd elasticsearch-7.15.1

# 内存配置调整(config/jvm.options)
-Xms512m
-Xmx512m

# 跨域配置(config/elasticsearch.yml)
http.cors.enabled: true
http.cors.allow-origin: "*"

步骤3:服务启动

# Windows环境
bin\elasticsearch.bat

# Linux环境
./bin/elasticsearch -d

常见问题处理: 启动时出现 max virtual memory areas vm.max_map_count [65530] is too low 错误时:

# Linux系统解决方案
sudo sysctl -w vm.max_map_count=262144

# Windows系统在配置文件中添加
bootstrap.memory_lock: false

验证部署结果:访问 http://localhost:9200 查看版本信息。

容器化部署方案

使用Docker部署能够快速搭建测试环境:

基础开发环境配置

docker run -d \
  --name es-7.15.1 \
  -p 9200:9200 \
  -p 9300:9300 \
  -e "discovery.type=single-node" \
  -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  -e "http.cors.enabled=true" \
  -e "http.cors.allow-origin=*" \
  elasticsearch:7.15.1

生产环境推荐配置

# 创建数据目录
mkdir -p /data/elasticsearch/{data,logs,config}
chmod 777 /data/elasticsearch/data

# 准备配置文件
echo "http.cors.enabled: true
http.cors.allow-origin: \"*\"
cluster.name: my-es-cluster
node.name: node-1" > /data/elasticsearch/config/elasticsearch.yml

# 启动容器
docker run -d \
  --name es-7.15.1-prod \
  -p 9200:9200 \
  -p 9300:9300 \
  -e "discovery.type=single-node" \
  -e "ES_JAVA_OPTS=-Xms1g -Xmx1g" \
  -v /data/elasticsearch/data:/usr/share/elasticsearch/data \
  -v /data/elasticsearch/logs:/usr/share/elasticsearch/logs \
  -v /data/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
  --ulimit memlock=-1:-1 \
  --ulimit nofile=65536:65536 \
  elasticsearch:7.15.1

Docker Compose 集成方案: 创建 docker-compose.yml 文件:

version: '3.8'
services:
  elasticsearch:
    image: elasticsearch:7.15.1
    container_name: es-7.15.1
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
      - http.cors.enabled=true
      - http.cors.allow-origin=*
    ports:
      - "9200:9200"
      - "9300:9300"
    volumes:
      - es-data:/usr/share/elasticsearch/data
      - ./elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536

  kibana:
    image: kibana:7.15.2
    container_name: kibana-7.15.1
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch

volumes:
  es-data:

启动命令:docker-compose up -d

部署方式对比

对比项 安装包部署 Docker部署
学习成本 较高 较低
资源占用 直接占用宿主机 容器额外开销
数据持久化 本地目录 需挂载volume
环境隔离 无隔离 完全隔离
推荐场景 生产环境 开发测试

实战案例:文章搜索系统

假设现有博客系统的文章表结构:

CREATE TABLE article (
    id BIGINT PRIMARY KEY,
    title VARCHAR(200),
    content TEXT,
    author VARCHAR(50),
    create_time DATETIME
);

使用 Elasticsearch 实现标题和内容的全文搜索,支持分页、高亮显示和时间排序。

索引创建与映射配置

通过 Kibana Dev Tools 执行:

PUT /article_index
{
  "mappings": {
    "properties": {
      "id": { "type": "long" },
      "title": { "type": "text", "analyzer": "ik_max_word" },
      "content": { "type": "text", "analyzer": "ik_max_word" },
      "author": { "type": "keyword" },
      "createTime": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }
    }
  }
}

关键配置点:中文搜索需要使用 IK 分词器,默认的 standard 分词器会将中文按字切分,影响搜索准确性。

Java客户端集成

在 SpringBoot 项目中引入依赖:

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

配置客户端连接:

@Configuration
public class EsConfig {

    @Bean
    public RestHighLevelClient esClient() {
        return new RestHighLevelClient(
            RestClient.builder(
                new HttpHost("localhost", 9200, "http")
            )
        );
    }
}

文档写入操作

@Service
public class ArticleEsService {

    @Autowired
    private RestHighLevelClient esClient;

    private static final String INDEX_NAME = "article_index";

    public void saveArticle(Article article) throws IOException {
        IndexRequest request = new IndexRequest(INDEX_NAME);
        request.id(article.getId().toString());

        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("id", article.getId());
        jsonMap.put("title", article.getTitle());
        jsonMap.put("content", article.getContent());
        jsonMap.put("author", article.getAuthor());
        jsonMap.put("createTime", article.getCreateTime().toString());

        request.source(jsonMap);
        esClient.index(request, RequestOptions.DEFAULT);
    }
}

搜索功能实现

public SearchResult searchArticles(String keyword, int pageNo, int pageSize) throws IOException {
    SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

    // 分页配置
    sourceBuilder.from((pageNo - 1) * pageSize);
    sourceBuilder.size(pageSize);

    // 时间倒序排序
    sourceBuilder.sort("createTime", SortOrder.DESC);

    // 多字段匹配查询
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    boolQuery.should(QueryBuilders.matchQuery("title", keyword).boost(2.0f));
    boolQuery.should(QueryBuilders.matchQuery("content", keyword));

    sourceBuilder.query(boolQuery);

    // 高亮显示配置
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    highlightBuilder.field("title");
    highlightBuilder.field("content");
    highlightBuilder.preTags("<em>").postTags("</em>");
    sourceBuilder.highlighter(highlightBuilder);

    searchRequest.source(sourceBuilder);
    SearchResponse response = esClient.search(searchRequest, RequestOptions.DEFAULT);

    // 结果解析
    List<ArticleDoc> articleList = new ArrayList<>();
    for (SearchHit hit : response.getHits().getHits()) {
        ArticleDoc doc = new ArticleDoc();
        doc.setId(Long.parseLong(hit.getId()));
        doc.setTitle(hit.getSourceAsMap().get("title").toString());
        doc.setContent(hit.getSourceAsMap().get("content").toString());
        doc.setAuthor(hit.getSourceAsMap().get("author").toString());

        // 高亮字段处理
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        if (highlightFields.containsKey("title")) {
            doc.setTitle(highlightFields.get("title").getFragments()[0].string());
        }
        if (highlightFields.containsKey("content")) {
            doc.setContent(highlightFields.get("content").getFragments()[0].string());
        }

        articleList.add(doc);
    }

    long total = response.getHits().getTotalHits().value;
    return new SearchResult(articleList, total, pageNo, pageSize);
}

查询DSL语法解析

Elasticsearch 的查询DSL可以通过与SQL对比来理解:

SQL语句示例:

SELECT * FROM article 
WHERE (title LIKE '%ES%' OR content LIKE '%ES%') 
AND author = '张三'
ORDER BY create_time DESC

对应的DSL查询:

{
  "query": {
    "bool": {
      "must": [
        {
          "bool": {
            "should": [
              { "match": { "title": "ES" } },
              { "match": { "content": "ES" } }
            ]
          }
        },
        { "term": { "author": "张三" } }
      ]
    }
  },
  "sort": [{ "createTime": "desc" }]
}

语法对应关系

  • must = SQL中的AND条件
  • should = SQL中的OR条件
  • must_not = SQL中的NOT条件
  • term = 精确匹配查询
  • match = 全文检索查询

中文分词优化

Elasticsearch 默认对中文支持有限,需要安装IK分词器:

  1. 下载对应版本:https://github.com/medcl/elasticsearch-analysis-ik
  2. 解压到 plugins/ik 目录
  3. 重启Elasticsearch服务

测试分词效果:

POST /_analyze
{
  "analyzer": "ik_max_word",
  "text": "搜索引擎技术"
}

IK分词器能够识别"搜索引擎"作为整体,同时支持"搜索"、"引擎"等细分词汇,显著提升中文搜索准确率。

实践经验总结

基于实际项目应用,得出以下关键经验:

  1. 适用场景选择:Elasticsearch 适合全文搜索和日志分析场景,但不适用于事务性操作。建议将搜索功能独立部署,核心业务数据仍使用关系型数据库。

  2. 渐进式学习:初期重点关注基础功能实现,无需过度深入分片、副本等高级特性。先确保单节点稳定运行,再逐步优化性能。

  3. 开发调试技巧:使用 Kibana Dev Tools 进行查询语句测试和调试,能够大幅提升开发效率。

对于大多数应用场景,掌握基础的数据建模、查询语法和分词配置即可满足需求,后续根据实际性能要求再深入研究底层原理和优化策略。

您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-3 15:27 , Processed in 0.073730 second(s), 38 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表