Java - ElasticSearch学习教程

Elasticsearch是一个基于Lucene的开源搜索引擎,利用倒排索引实现高效搜索。文章介绍了其安装过程、数据操作以及在Springboot中的集成,还探讨了分页查询、排序和权重设置等优化策略。
摘要由CSDN通过智能技术生成

Elasticsearch介绍

Elasticsearch是一个开源的搜索引擎,它可以实现全文检索、分布式搜索、分析等功能。它使用Lucene作为搜索引擎的核心,通过HTTP RESTful API提供数据索引和搜索服务。Elasticsearch被广泛应用于企业搜索、日志分析、安全分析等领域。本文将介绍如何入门Elasticsearch。

Elasticsearch的倒排索引

Elasticsearch是一种基于Lucene的分布式搜索引擎,它使用倒排索引(Inverted Index)来加速搜索。倒排索引是一种数据结构,它将文档中的每个单词映射到包含该单词的文档列表中,以便快速地进行文本搜索。
在传统的索引中,文档是按照文档ID进行排序的,而倒排索引则是按照单词进行排序的。举例来说,如果有两篇文档,其中一篇包含单词“Elasticsearch”,另一篇包含单词“Java”,那么倒排索引将会是这样的:

Elasticsearch -> Doc1
Java -> Doc2

这样的索引结构使得搜索引擎能够快速地找到包含特定单词的文档,并将它们按照相关性排序。在搜索一个查询时,搜索引擎只需要找到查询中包含的单词所对应的文档列表,并对这些文档进行排序,然后返回排名最高的文档即可。
倒排索引的优点是它可以快速地找到包含特定单词的文档,而不需要遍历整个文档集合。这使得搜索引擎能够处理大量的文档,并在短时间内响应查询请求。在Elasticsearch中,倒排索引是通过Lucene实现的,而且它可以处理多种类型的数据,包括文本、数字、地理位置等。

安装Elasticsearch

Elasticsearch支持多种操作系统,包括Windows、Linux、Mac OS等。以下是在Linux上安装

Elasticsearch的步骤:

下载Elasticsearch的安装包,可以从Elasticsearch官网(https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.12.0-windows-x86_64.zip)下载。

解压安装包,执行以下命令:

tar -zxvf elasticsearch-7.6.1-linux-x86_64.tar.gz

进入Elasticsearch的bin目录,启动Elasticsearch:

cd elasticsearch-7.6.1/bin
./elasticsearch

执行以下命令,测试Elasticsearch是否正常运行:

curl http://localhost:9200/

如果返回类似以下结果,则表示Elasticsearch已成功安装:

{
  "name" : "node-1",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "n8Jy9VbTRtWJ8z4HJ0jQ8g",
  "version" : {
    "number" : "7.6.1",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "aa751e09be0a5072e8570670309b1f12348f023b",
    "build_date" : "2020-02-29T00:15:25.529771Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

使用Elasticsearch

创建索引

Elasticsearch中的数据存储在索引中,可以将索引看做是关系型数据库中的表。以下是创建一个名为test的索引的步骤:

执行以下命令,创建名为test的索引:

curl -X PUT "localhost:9200/test?pretty"

如果返回类似以下结果,则表示索引已成功创建:

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "test"
}

在索引中添加数据:

curl -X PUT "localhost:9200/test/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
  "title": "Elasticsearch",
  "author": "John Doe",
  "content": "Elasticsearch is a search engine based on Lucene."
}

如果返回类似以下结果,则表示数据已成功添加到索引中:

{
  "_index" : "test",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

搜索

执行以下命令,搜索包含“Elasticsearch”的数据:

curl -X GET "localhost:9200/test/_search?q=Elasticsearch&pretty"

如果返回类似以下结果,则表示搜索结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "title" : "Elasticsearch",
          "author" : "John Doe",
          "content" : "Elasticsearch is a search engine based on Lucene."
        }
      }
    ]
  }
}

执行以下命令,搜索包含“search engine”的数据:

curl -X GET "localhost:9200/test/_search" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "content": "search engine"
    }
  }
}

如果返回类似以下结果,则表示搜索结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "title" : "Elasticsearch",
          "author" : "John Doe",
          "content" : "Elasticsearch is a search engine based on Lucene."
        }
      }
    ]
  }
}

Springboot集成Elasticsearch

添加Elasticsearch依赖

在pom.xml文件中添加Elasticsearch依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

配置Elasticsearch

在application.properties文件中添加Elasticsearch的配置信息:

spring.data.elasticsearch.cluster-name=my-application
spring.data.elasticsearch.cluster-nodes=localhost:9300

创建实体类

创建一个实体类,表示要在Elasticsearch中存储的数据。

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Document(indexName = "book", type = "book")
public class Book {
    @Id
    private String id;
    private String title;
    private String author;
    private String content;
}

@Data:Lombok注解,自动生成getter、setter、equals、hashCode和toString方法。

@NoArgsConstructor:Lombok注解,自动生成无参构造函数。

@AllArgsConstructor:Lombok注解,自动生成全参构造函数。

@Builder:Lombok注解,自动生成builder方法。

@Document:Elasticsearch注解,指定索引名称和类型。

@Id:Elasticsearch注解,指定文档ID。

创建Elasticsearch仓库

创建一个继承自ElasticsearchRepository的接口。

public interface BookRepository extends ElasticsearchRepository<Book, String> {
}

ElasticsearchRepository是Spring Data Elasticsearch提供的仓库接口,它提供了一些基本的CRUD操作。

使用Elasticsearch

在业务代码中使用BookRepository接口操作Elasticsearch。

@RestController
@RequestMapping("/book")
public class BookController {
    @Autowired
    private BookRepository bookRepository;
    @PostMapping("/")
    public Book save(@RequestBody Book book) {
        return bookRepository.save(book);
    }
    @GetMapping("/{id}")
    public Optional<Book> findById(@PathVariable String id) {
        return bookRepository.findById(id);
    }
    @GetMapping("/")
    public Iterable<Book> findAll() {
        return bookRepository.findAll();
    }
    @GetMapping("/search")
    public Iterable<Book> search(@RequestParam String keyword) {
        String wildcardQuery = String.format("*%s*", keyword);
        QueryStringQueryBuilder builder = QueryBuilders.queryStringQuery(wildcardQuery);
        Iterable<Book> books = bookRepository.search(builder);
        return books;
    }
}

@RestController:Spring MVC注解,标识这是一个RESTful接口。

@RequestMapping(“/book”):Spring MVC注解,指定接口的URL路径。

@Autowired:Spring注解,自动注入依赖。

@PostMapping(“/”):Spring MVC注解,指定POST请求的URL路径。

@RequestBody:Spring MVC注解,将请求体转换成Java对象。

@GetMapping(“/{id}”):Spring MVC注解,指定GET请求的URL路径,使用{id}占位符表示参数。

@PathVariable:Spring MVC注解,将URL中的参数映射到方法的参数中。

@GetMapping(“/”):Spring MVC注解,指定GET请求的URL路径。

@RequestParam:Spring MVC注解,将URL中的参数映射到方法的参数中。

QueryStringQueryBuilder:Elasticsearch查询构建器,用于构建查询语句。

QueryBuilders.queryStringQuery(wildcardQuery):创建一个查询字符串查询。

Elasticsearch三种分页查询方法

方法一:使用from和size参数

Elasticsearch的from和size参数可以用来控制查询结果的分页。from参数指定开始返回结果的位置,size参数指定返回结果的数量。例如,如果要查询第11个到第20个结果,可以设置from=10,size=10。
在Java中,可以使用Elasticsearch的SearchRequestBuilder来设置from和size参数。

SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index)
        .setTypes(type)
        .setQuery(QueryBuilders.matchAllQuery())
        .setFrom(0)
        .setSize(10);
SearchResponse response = searchRequestBuilder.get();

上面的代码将查询第1页的结果,每页返回10条数据。

方法二:使用scroll API

Elasticsearch的scroll API可以用来处理大量数据的分页查询。它的工作原理是,先查询一次,获取第一页的数据,并返回一个scroll_id;然后,使用scroll_id来获取下一页的数据,直到数据全部查询完毕。scroll API的优点是可以处理大量数据的分页查询,并且每个分页查询的时间相对稳定。
在Java中,可以使用Elasticsearch的SearchScrollRequestBuilder来实现scroll API的分页查询。

SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index)
        .setTypes(type)
        .setQuery(QueryBuilders.matchAllQuery())
        .setScroll(new TimeValue(60000))
        .setSize(10);
SearchResponse response = searchRequestBuilder.get();
String scrollId = response.getScrollId();
while (true) {
    SearchScrollRequestBuilder scrollRequestBuilder = client.prepareSearchScroll(scrollId)
            .setScroll(new TimeValue(60000));
    SearchResponse scrollResponse = scrollRequestBuilder.get();
    scrollId = scrollResponse.getScrollId();
    SearchHits hits = scrollResponse.getHits();
    if (hits.getHits().length == 0) {
        break;
    }
    for (SearchHit hit : hits.getHits()) {
        // 处理每一条数据
    }
}
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.addScrollId(scrollId);
client.clearScroll(clearScrollRequest);

上面的代码将查询所有的结果,并对每个结果进行处理。

方法三:使用分片查询

Elasticsearch的分片查询可以用来加速分页查询。它的工作原理是,将索引分成多个分片,每个分片都可以独立处理查询请求。当查询请求到达时,Elasticsearch会将请求分发到多个分片上,并将每个分片的查询结果合并起来。分片查询的优点是可以加速分页查询,并且可以处理大量数据的分页查询。
在Java中,可以使用Elasticsearch的SearchRequestBuilder来实现分片查询的分页查询。

SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index)
        .setTypes(type)
        .setQuery(QueryBuilders.matchAllQuery())
        .setFrom(0)
        .setSize(10)
        .setSearchType(SearchType.DFS_QUERY_THEN_FETCH);
SearchResponse response = searchRequestBuilder.get();
SearchHits hits = response.getHits();
for (SearchHit hit : hits.getHits()) {
    // 处理每一条数据
}

上面的代码将使用分片查询来查询第1页的结果,每页返回10条数据。

Elasticsearch的排序和权重设置

Elasticsearch的排序和权重设置可以通过查询时设置排序字段和排序方式,以及设置查询条件的权重来实现。

排序设置

可以使用Elasticsearch的查询API实现排序设置,例如使用SearchRequestBuilder的addSort方法,设置排序字段和排序方式,如下所示:

SearchRequestBuilder searchRequestBuilder = client.prepareSearch("index");
searchRequestBuilder.setTypes("type");
searchRequestBuilder.addSort("field", SortOrder.DESC);

上述代码中,设置了按照“field”字段进行倒序排序,也可以设置为SortOrder.ASC进行升序排序。

权重设置

可以使用Elasticsearch的查询API实现查询条件的权重设置,例如使用QueryBuilder的boost方法,为查询条件设置权重,如下所示:

QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("field1", "value1").boost(2.0f))
                .should(QueryBuilders.matchQuery("field2", "value2").boost(1.0f));

上述代码中,设置了对“field1”字段的查询权重为2.0,对“field2”字段的查询权重为1.0。这意味着匹配“field1”字段的文档将比匹配“field2”字段的文档更加相关。

Elasticsearch查询优化

  1. 选择合适的查询类型
    Elasticsearch提供了多种查询类型,如Match Query、Term Query、Range Query等。不同的查询类型适用于不同的场景,选择合适的查询类型可以提高查询性能。

  2. 设置合适的分片数量和大小
    Elasticsearch将索引分为多个分片,分片数量和大小对查询性能有重要影响。如果分片过多,每个分片的大小会变小,但是查询时需要访问更多的分片,会降低查询性能。如果分片过少,每个分片的大小会变大,但是会导致集群负载不均衡。因此,需要根据实际情况选择合适的分片数量和大小。

  3. 缓存查询结果
    Elasticsearch提供了缓存查询结果的功能,可以减少相同查询的响应时间。可以将经常使用的查询结果缓存起来,以提高查询性能。

  4. 使用搜索建议
    Elasticsearch提供了搜索建议(Suggest)功能,可以为用户提供实时的查询建议。搜索建议可以降低用户的查询次数,提高用户体验。

  5. 避免全文搜索
    全文搜索是Elasticsearch的核心功能,但是全文搜索会消耗大量的资源。可以尝试避免全文搜索,例如使用Filter和Aggregation等方式,以提高查询性能。

  6. 选择合适的节点
    Elasticsearch是一个分布式系统,查询请求可能会被发送到不同的节点。可以通过选择合适的节点来提高查询性能,例如选择较快的节点或者与查询相关的节点。

Elasticsearch的缺点

Elasticsearch是一种高性能、可扩展、分布式的搜索引擎,但它也有一些缺点,包括以下几个方面:

  1. 存储成本较高:Elasticsearch需要大量的磁盘空间来存储索引和数据。对于小型应用程序来说,存储成本可能不是一个大问题,但对于大型应用程序来说,需要考虑存储成本和性能之间的平衡。

  2. 硬件要求高:Elasticsearch需要高性能的硬件来支持大量的搜索请求和索引更新。这可能需要投入一定的资金来购买高性能的硬件。

  3. 分布式系统的复杂性:Elasticsearch是一个分布式系统,它需要配置和管理多个节点来实现高可用性和负载均衡。这增加了系统的复杂性和维护成本。

  4. 内存消耗较大:Elasticsearch需要大量的内存来支持索引和搜索操作。对于大型索引和高并发负载,需要投入更多的内存来保证系统的性能。

  5. 数据一致性问题:Elasticsearch是一个分布式系统,数据的一致性可能会受到网络延迟和节点故障等因素的影响。这可能会导致数据不一致的问题,需要采取一些措施来保证数据的一致性。

Elasticsearch是一种强大的搜索引擎,但在实际中也存在一些缺点。在使用Elasticsearch时,需要权衡各种因素,包括性能、成本、复杂性和数据一致性等,来选择最适合自己应用场景的方案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值