ElasticSearch之SpringDataElasticSearch使用


什么是SpringData

 

Spring Data是一個用於簡化數據庫訪問,並支持雲服務的開源框架。其主要目標是使得對數據的訪問變得方便快
捷,並支持map-reduce框架和雲計算數據服務。 Spring Data可以極大的簡化JPA的寫法,可以在幾乎不用寫實現
的情況下,實現對數據的訪問和操作。除了CRUD外,還包括如分頁、排序等一些常用的功能。
Spring Data的官網:http://projects.spring.io/spring-data/

 

什么是SpringDataElasticSearch

 

 

Spring Data ElasticSearch 基於 spring data API 簡化 elasticSearch操作,將原始操作elasticSearch的客戶端API
進行封裝 。Spring Data為Elasticsearch項目提供集成搜索引擎。Spring Data Elasticsearch POJO的關鍵功能區域
為中心的模型與Elastichsearch交互文檔和輕松地編寫一個存儲庫數據訪問層。
官方網站:http://projects.spring.io/spring-data-elasticsearch/

 

創建工程並且實現使用SpringDataElasticSearch創建索引和文檔

第一步:創建一個maven工程,導入依賴

  <dependency>
      <groupId>org.elasticsearch</groupId>
      <artifactId>elasticsearch</artifactId>
      <version>5.6.8</version>
    </dependency>
    <dependency>
      <groupId>org.elasticsearch.client</groupId>
      <artifactId>transport</artifactId>
      <version>5.6.8</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-to-slf4j</artifactId>
      <version>2.9.1</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.24</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>1.7.21</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.12</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.8.1</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.8.1</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.8.1</version>
    </dependency>

    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-elasticsearch</artifactId>
      <version>3.0.5.RELEASE</version>
      <exclusions>
        <exclusion>
          <groupId>org.elasticsearch.plugin</groupId>
          <artifactId>transport‐netty4‐client</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.0.4.RELEASE</version>
    </dependency>

  

第二步:創建實體Article

基於spring data elasticsearch注解配置索引、映射和實體的

package com.wish.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

//@Document 文檔對象 (索引信息、文檔類型)
@Document(indexName = "blog3",type = "table03")
public class Article {

    /*
    @Document(indexName="blob3",type="article"):
        indexName:索引的名稱(必填項)
        type:索引的類型
    @Id:主鍵的唯一標識

    @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type=FieldType.text)
        每個文檔的字段配置(類型、是否分詞、是否存儲、分詞器 )
        index:是否設置分詞
        analyzer:存儲時使用的分詞器
        searchAnalyze:搜索時使用的分詞器
        store:是否存儲
        type: 數據類型
     */

    @Id
    @Field(store = true,index = false,type = FieldType.Integer)
    private Integer id;

    @Field(index = true,analyzer = "ik_smart",store = true,searchAnalyzer = "ik_smart",type = FieldType.text)
    private String title;


    @Field(index = true,analyzer = "ik_smart",store = true,searchAnalyzer = "ik_smart",type = FieldType.text)
    private String content;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "Table01{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }
}

  

第三步:編寫dao層

package com.wish.dao;

import com.wish.entity.Article;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> {
}

  

第三步:編寫service

package com.wish.service;

import com.wish.entity.Article;

public interface ArticleService {

    public void save(Article article);

}

  

第四步:編寫service的實現類

package com.wish.service.impl;

import com.wish.dao.ArticleRepository;
import com.wish.entity.Article;
import com.wish.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;

@Service public class ArticleServiceImpl implements ArticleService { @Autowired private ArticleRepository articleRepository; @Override public void save(Article article) { articleRepository.save(article); } }

  

第五步:配置applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/data/elasticsearch
        http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd
        ">
    <!--掃描DAO包,自動創建實例-->
    <elasticsearch:repositories base-package="com.wish.dao"/>
    <!--掃描service包,創建service的實體-->
    <context:component-scan base-package="com.wish.service"/>

    <!--配置 ElasticSearch模的連接-->
    <elasticsearch:transport-client id="client" cluster-nodes="127.0.0.1:9300" cluster-name="my-elasticsearch"/>

    <!-- ElasticSearch模模板對象-->
    <bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
        <constructor-arg name="client" ref="client"></constructor-arg>
    </bean>
</beans>

  

第六步:創建測試類SpringDataESTest

package com.wish;

import com.wish.entity.Article;
import com.wish.service.ArticleService;
import org.elasticsearch.client.transport.TransportClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringDataESTest {

    @Autowired
    private ArticleService articleService;

    @Autowired
    private TransportClient client;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    /**
     * 創建索引和映射
     */
    @Test
    public void createIndex() {
        elasticsearchTemplate.createIndex(Article.class);
        elasticsearchTemplate.putMapping(Article.class);
    }

    /**
     * 測試保存文檔
     */
    @Test
    public void saveArticle() {
        Article article = new Article();
        article.setId(100);
        article.setTitle("測試SpringData ElasticSearch");
        article.setContent("Spring Data ElasticSearch 基於 spring data API 簡化 elasticSearch操\n" +
                "                作,將原始操作elasticSearch的客戶端API 進行封裝\n" +
                "                Spring Data為Elasticsearch Elasticsearch項目提供集成搜索引擎");
        articleService.save(article);
    }
}

  

創建索引和映射的效果和遇到錯誤

 

 

 

 

 

 

 

 

 

注意:如果創建時報一下錯誤

1.org.springframework.data.elasticsearch.repository.support.AbstractElasticsearchRepository - failed to load elasticsearch nodes : org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{-jhPfiM0Sh6cKPV4rCAKlg}{localhost}{127.0.0.1:9300}]

解決:(1)刪除掉data文件夾,進行重啟(2)注意配置文件中的cluster‐name的值與圖片中紅圈的一樣

2.org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.wish.SpringDataESTest': Unsatisfied dependency expressed through field 'articleService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.wish.service.ArticleService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

解決:這個錯是因為一開寫着急了,service的實現類沒有用@service注解標識

 

創建文檔的效果

 

 

 

 

 

SpringDataElasticSearch的常用操作

增刪改查方法測試

修改service和service實現類

package com.wish.service;

import com.wish.entity.Article;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface ArticleService {

    //保存
    public void save(Article article);
    //刪除
    public void delete(Article article);
    //查詢全部
    public Iterable<Article> findAll();
    //分頁查詢
    public Page<Article> findAll(Pageable pageable);


}

  

package com.wish.service.impl;

import com.wish.dao.ArticleRepository;
import com.wish.entity.Article;
import com.wish.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    @Override
    public void save(Article article) {
        articleRepository.save(article);
    }

    @Override
    public void delete(Article article) {
        articleRepository.delete(article);
    }

    @Override
    public Iterable<Article> findAll() {
        Iterable<Article> iter = articleRepository.findAll();
        return iter;
    }

    @Override
    public Page<Article> findAll(Pageable pageable) {
        return articleRepository.findAll(pageable);
    }
}

  

增加文檔

 /**測試保存*/
    @Test
    public void save(){
        Article article = new Article();
        article.setId(1001);
        article.setTitle("elasticSearch 3.0版本發布");
        article.setContent("ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用戶能力的\n" +
                "                全文搜索引擎,基於RESTful web接口");
                articleService.save(article);
    }

 

效果 

 

 

 

 修改文檔

/**測試更新*/
    @Test
    public void update(){
        Article article = new Article();
        article.setId(1001);
        article.setTitle("[更新]elasticSearch 3.0版本發布");
        article.setContent("[更新]ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用戶能力的\n" +
                "                全文搜索引擎,基於RESTful web接口");
                articleService.save(article);
    }

  

效果

 

 

 

 

刪除文檔

  /**測試刪除*/
    @Test
    public void delete(){
        Article article = new Article();
        article.setId(1001);
        articleService.delete(article);
    }

  

效果

 

 

 

 

批量添加文檔

  /**批量插入*/
    @Test
    public void save100(){
        for(int i=1;i<=20;i++){
            Article article = new Article();
            article.setId(i);
            article.setTitle(i+"elasticSearch 3.0版本發布..,更新");
            article.setContent(i+"ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用\n" +
                    "                    戶能力的全文搜索引擎,基於RESTful web接口");
                    articleService.save(article);
        }
    }

  

效果

 

 

 

 

分頁查詢文檔

  /**分頁查詢*/
    @Test
    public void findAllPage() {
        Pageable pageable = PageRequest.of(1, 10);
        Page<Article> page = articleService.findAll(pageable);
        for (Article article : page.getContent()) {
            System.out.println(article);
        }
    }

 

效果  

 

 

 

 常用查詢命名規則

 

 帶條件查詢方法測試

修改dao層

package com.wish.dao;

import com.wish.entity.Article;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> {
    //根據標題查詢
    List<Article> findByTitle(String condition);
    //根據標題查詢(含分頁)
    Page<Article> findByTitle(String condition, Pageable pageable);

}

  

修改service層和service的實現層

package com.wish.service;

import com.wish.entity.Article;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface ArticleService {

    //保存
    public void save(Article article);
    //刪除
    public void delete(Article article);
    //查詢全部
    public Iterable<Article> findAll();
    //分頁查詢
    public Page<Article> findAll(Pageable pageable);

    //根據標題查詢
    List<Article> findByTitle(String condition);
    //根據標題查詢(含分頁)
    Page<Article> findByTitle(String condition, Pageable pageable);


}

  

package com.wish.service.impl;

import com.wish.dao.ArticleRepository;
import com.wish.entity.Article;
import com.wish.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    @Override
    public void save(Article article) {
        articleRepository.save(article);
    }

    @Override
    public void delete(Article article) {
        articleRepository.delete(article);
    }

    @Override
    public Iterable<Article> findAll() {
        Iterable<Article> iter = articleRepository.findAll();
        return iter;
    }

    @Override
    public Page<Article> findAll(Pageable pageable) {
        return articleRepository.findAll(pageable);
    }

    @Override
    public List<Article> findByTitle(String condition) {
        return articleRepository.findByTitle(condition);
    }

    @Override
    public Page<Article> findByTitle(String condition, Pageable pageable) {
        return articleRepository.findByTitle(condition,pageable);
    }
}

  

帶條件查詢

/**條件查詢*/
    @Test
    public void findByTitle(){
        String condition = "版本";
        List<Article> articleList = articleService.findByTitle(condition);
        for(Article article:articleList){
            System.out.println(article);
        }
    }

  

效果

 

 

 

 

帶條件分頁查詢

 /**條件分頁查詢*/
    @Test
    public void findByTitlePage(){
        String condition = "版本";
        Pageable pageable = PageRequest.of(2,5);
        Page<Article> page = articleService.findByTitle(condition,pageable);
        int count=0;
        for(Article article:page.getContent()){
            count++;
            System.out.println(article);
        }
        System.out.println("總記錄數:"+count);
    }

  

 效果

 

 

使用Elasticsearch的原生查詢對象進行查詢

 

 @Test
    public void findByNativeQuery() {
        //創建一個SearchQuery對象
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
        //設置查詢條件,此處可以使用QueryBuilders創建多種查詢
                .withQuery(QueryBuilders.queryStringQuery("版本").defaultField("title"))
        //還可以設置分頁信息
                                .withPageable(PageRequest.of(1, 5))
        //創建SearchQuery對象
                                .build();
        //使用模板對象執行查詢
        elasticsearchTemplate.queryForList(searchQuery, Article.class).forEach(article ->  System.out.println(article));
    }

  

效果

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM