最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot集成ElasticSearch實(shí)現(xiàn)搜索引擎的示例

 更新時(shí)間:2017年11月02日 10:04:35   作者:牛麥康納  
這篇文章主要介紹了Spring Boot集成ElasticSearch實(shí)現(xiàn)搜索引擎的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

Elastic Search是一個(gè)開(kāi)源的,分布式,實(shí)時(shí)搜索和分析引擎。Spring Boot為Elasticsearch及Spring Data Elasticsearch提供的基于它的抽象提供了基本的配置。Spring Boot提供了一個(gè)用于聚集依賴的spring-boot-starter-data-elasticsearch 'StarterPOM'。

ElasticSearch作為搜索引擎,我們需要解決2大問(wèn)題:

1,  如何將被搜索的數(shù)據(jù)在ES上創(chuàng)建反向索引
2,  Java代碼如何與ES交互

其中第一個(gè)大問(wèn)題又分為兩個(gè)小問(wèn)題

1.1,如何初始化已有的數(shù)據(jù)
1.2,如何同步增量數(shù)據(jù)

第二個(gè)大問(wèn)題也有兩種集成方式

2.1 Spring Data 9300端口集成
2.2 Restful API 9200端口集成

本篇先解決第二大問(wèn)題。

第一種方式,利用RestAPI方式,也叫Jest方式:

示例代碼:https://github.com/yejingtao/forblog/tree/master/demo-jest-elasticsearch

Pom.xml:

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
 <modelVersion>4.0.0</modelVersion> 
 
 <groupId>yejingtao.demo.springcloud</groupId> 
 <artifactId>demo-jest-elasticsearch</artifactId> 
 <version>0.0.1-SNAPSHOT</version> 
 <packaging>jar</packaging> 
 
 <name>demo-jest-elasticsearch</name> 
 <url>http://maven.apache.org</url> 
 
 <properties> 
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
 </properties> 
  
 <parent> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>1.5.6.RELEASE</version> 
  </parent> 
   
  <dependencies> 
    <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-web</artifactId> 
    </dependency> 
    <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-data-elasticsearch</artifactId> 
    </dependency> 
    <dependency> 
      <groupId>io.searchbox</groupId> 
      <artifactId>jest</artifactId> 
    </dependency> 
    <dependency> 
      <groupId>net.java.dev.jna</groupId> 
      <artifactId>jna</artifactId> 
    </dependency> 
  </dependencies> 
</project> 

Application.yml:

server: 
 port: 7081 
 
spring: 
 elasticsearch: 
  jest: 
   uris: 
   - http://192.168.226.133:9200 
   read-timeout: 5000 

注意這里是9200端口

主程序:最簡(jiǎn)單的Spring boot啟動(dòng)程序:

@SpringBootApplication 
public class ESApplication { 
 
  public static void main(String[] args) { 
    SpringApplication.run(ESApplication.class); 
  } 
} 

定義好ES中的實(shí)體類和對(duì)ES操作的接口:

public class Entity implements Serializable{ 
 
  private static final long serialVersionUID = -763638353551774166L; 
   
  public static final String INDEX_NAME = "index_entity"; 
   
  public static final String TYPE = "tstype"; 
 
  private Long id; 
   
  private String name; 
   
  public Entity() { 
    super(); 
  } 
   
  public Entity(Long id, String name) { 
    this.id = id; 
    this.name = name; 
  } 
 
  public Long getId() { 
    return id; 
  } 
 
  public void setId(Long id) { 
    this.id = id; 
  } 
 
  public String getName() { 
    return name; 
  } 
 
  public void setName(String name) { 
    this.name = name; 
  } 
   
   
} 
public interface CityESService { 
   
  void saveEntity(Entity entity); 
   
  void saveEntity(List<Entity> entityList); 
   
  List<Entity> searchEntity(String searchContent); 
} 

接口實(shí)現(xiàn):

@Service 
public class CityESServiceImpl implements CityESService{ 
   
  private static final Logger LOGGER = LoggerFactory.getLogger(CityESServiceImpl.class); 
   
  @Autowired 
  private JestClient jestClient; 
   
  @Override 
  public void saveEntity(Entity entity) { 
    Index index = new Index.Builder(entity).index(Entity.INDEX_NAME).type(Entity.TYPE).build(); 
    try { 
      jestClient.execute(index); 
      LOGGER.info("ES 插入完成"); 
    } catch (IOException e) { 
      e.printStackTrace(); 
      LOGGER.error(e.getMessage()); 
    } 
  } 
   
   
  /** 
   * 批量保存內(nèi)容到ES 
   */ 
  @Override 
  public void saveEntity(List<Entity> entityList) { 
    Bulk.Builder bulk = new Bulk.Builder(); 
    for(Entity entity : entityList) { 
      Index index = new Index.Builder(entity).index(Entity.INDEX_NAME).type(Entity.TYPE).build(); 
      bulk.addAction(index); 
    }     
    try { 
      jestClient.execute(bulk.build()); 
      LOGGER.info("ES 插入完成"); 
    } catch (IOException e) { 
      e.printStackTrace(); 
      LOGGER.error(e.getMessage()); 
    } 
  } 
   
  /** 
   * 在ES中搜索內(nèi)容 
   */ 
  @Override 
  public List<Entity> searchEntity(String searchContent){ 
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
    //searchSourceBuilder.query(QueryBuilders.queryStringQuery(searchContent)); 
    //searchSourceBuilder.field("name"); 
    searchSourceBuilder.query(QueryBuilders.matchQuery("name",searchContent)); 
    Search search = new Search.Builder(searchSourceBuilder.toString()) 
        .addIndex(Entity.INDEX_NAME).addType(Entity.TYPE).build(); 
    try { 
      JestResult result = jestClient.execute(search); 
      return result.getSourceAsObjectList(Entity.class); 
    } catch (IOException e) { 
      LOGGER.error(e.getMessage()); 
      e.printStackTrace(); 
    } 
    return null;     
  } 
} 

這里插入數(shù)據(jù)的方式給了兩種,一種是單次API直接插入,一種是利用ES的bulk批量插入。

做一個(gè)controller方面我們測(cè)試:

啟動(dòng)后在瀏覽器中請(qǐng)求http://localhost:7081/entityController/search?name=%E4%BA%BA%E6%89%8B%E4%BA%95

得到結(jié)果:

這里只返回了9條記錄,而理論上ES默認(rèn)的size是10,應(yīng)該不是分頁(yè)的問(wèn)題,而是只能檢索出9條匹配記錄,用Kibana連上相同的搜索確認(rèn)下:

這里用的是standard分詞方式,將每個(gè)中文都作為了一個(gè)term,凡是包含“人”“手”“井”的都被搜索了出來(lái),只是評(píng)分不同,如果想支持只能中文索引需要依賴ik插件

OK,RestFul方式對(duì)ElasticSearch的檢索已經(jīng)搞定了,更多的擴(kuò)展可以慢慢研究下QueryBuilders里的源碼和批注。

第二種方式,利用Spring Data客戶端方式:

事先說(shuō)明此方式有個(gè)弊端,讓我掉了坑里好久才爬上來(lái),Spring Data ElasticSearch必須與ElasticSearch版本相匹配,否則在對(duì)接時(shí)ES端會(huì)報(bào)版本不匹配錯(cuò)誤,例如我ES是5.6.1版本,Spring boot是1.5.6版本,錯(cuò)誤如下:

為解決這個(gè)問(wèn)題我查找了一些資料,Spring Data與elasticsearch版本對(duì)應(yīng)關(guān)系如下:

spring data elasticsearch

elasticsearch

3.0.0.RC2

5.5.0

3.0.0.M4

5.4.0

2.0.4.RELEASE

2.4.0

2.0.0.RELEASE

2.2.0

1.4.0.M1

1.7.3

1.3.0.RELEASE

1.5.2

1.2.0.RELEASE

1.4.4

1.1.0.RELEASE

1.3.2

1.0.0.RELEASE

1.1.1

而我用的Spring Boot 1.5.6版本對(duì)應(yīng)的Spring Data ElasticSearch是2.1.6版本,不支持5.X的ES,所以報(bào)錯(cuò)。到本博文撰寫(xiě)為止,Spring Boot的RELEASE版本最新的是1.5.8,對(duì)應(yīng)的Spring Data ElasticSearch是2.1.8,仍不支持5.X的ES,所以如果一定要使用Java客戶端方式集成ES只能放棄Spring Boot直接使用Spring Data和Spring MVC,或者降低ES的版本使之與Spring boot匹配。

示例代碼:https://github.com/yejingtao/forblog/tree/master/demo-data-elasticsearch

pom.xml依賴:

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
 <modelVersion>4.0.0</modelVersion> 
 
 <groupId>yejingtao.demo.springcloud</groupId> 
 <artifactId>demo-data-elasticsearch</artifactId> 
 <version>0.0.1-SNAPSHOT</version> 
 <packaging>jar</packaging> 
 
 <name>demo-data-elasticsearch</name> 
 <url>http://maven.apache.org</url> 
 
 <properties> 
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
 </properties> 
  
 <parent> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>1.5.8.RELEASE</version> 
  </parent> 
   
  <dependencies> 
    <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-web</artifactId> 
    </dependency> 
    <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-data-elasticsearch</artifactId> 
    </dependency> 
  </dependencies> 
</project> 

不再引用Jest。

application.yml:

server: 
 port: 7081 
 
spring: 
 data: 
  elasticsearch: 
   cluster-nodes: 192.168.226.133:9300 
   cluster-name: my-es 
   repositories: 
    enabled: true 

注意這里是9300端口

Controller、主程序、Service接口同Jest項(xiàng)目不變,不再羅列

實(shí)體類稍作變化,指定ES中的index和type:

@Document(indexName="index_entity", type="tstype") 

多一個(gè)Repository接口,無(wú)需實(shí)現(xiàn)類,spring data標(biāo)準(zhǔn)用法:

/** 
 * Entity ES操作類 
 * @author yejingtao 
 * 
 */ 
public interface EntityRepository extends ElasticsearchRepository<Entity,Long>{ 
 
} 

Service實(shí)現(xiàn)類與Jest的天壤之別了,從語(yǔ)法上可以看出更像是對(duì)數(shù)據(jù)庫(kù)層的操作:

@Service 
public class CityESServiceImpl implements CityESService{ 
   
  private static final Logger LOGGER = LoggerFactory.getLogger(CityESServiceImpl.class); 
   
  int PAGE_SIZE = 15; //默認(rèn)分頁(yè)大小 
   
  int PAGE_NUMBER = 0; //默認(rèn)當(dāng)前分頁(yè) 
   
  String SCORE_MODE_SUM = "sum"; //權(quán)重分求和模式 
   
  Float MIN_SCORE = 10.0F; //由于無(wú)相關(guān)性的分值默認(rèn)為1, 設(shè)置權(quán)重分最小值為10 
   
  @Autowired 
  EntityRepository entityRepository; 
   
  /** 
   * 保存內(nèi)容到ES 
   */ 
  @Override 
  public Long saveEntity(Entity entity) { 
    Entity entityResult = entityRepository.save(entity); 
    return entityResult.getId(); 
  } 
   
  /** 
   * 在ES中搜索內(nèi)容 
   */ 
  @Override 
  public List<Entity> searchEntity(int pageNumber, int pageSize, String searchContent){ 
    if(pageSize==0) { 
      pageSize = PAGE_SIZE; 
    } 
    if(pageNumber<0) { 
      pageNumber = PAGE_NUMBER; 
    } 
     
    SearchQuery searchQuery = getEntitySearchQuery(pageNumber,pageSize,searchContent); 
     
    LOGGER.info("\n searchCity: searchContent [" + searchContent + "] \n DSL = \n "  
        + searchQuery.getQuery().toString()); 
 
     
    Page<Entity> cityPage = entityRepository.search(searchQuery); 
    return cityPage.getContent(); 
  } 
   
  /** 
   * 組裝搜索Query對(duì)象 
   * @param pageNumber 
   * @param pageSize 
   * @param searchContent 
   * @return 
   */ 
  private SearchQuery getEntitySearchQuery(int pageNumber, int pageSize, String searchContent) { 
    FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery() 
        .add(QueryBuilders.matchPhraseQuery("name", searchContent), 
            ScoreFunctionBuilders.weightFactorFunction(1000)) 
        //.add(QueryBuilders.matchPhraseQuery("other", searchContent), 
            //ScoreFunctionBuilders.weightFactorFunction(1000)) 
        .scoreMode(SCORE_MODE_SUM).setMinScore(MIN_SCORE); 
    //設(shè)置分頁(yè),否則只能按照ES默認(rèn)的分頁(yè)給 
    Pageable pageable = new PageRequest(pageNumber, pageSize); 
    return new NativeSearchQueryBuilder().withPageable(pageable).withQuery(functionScoreQueryBuilder).build(); 
  } 
   
} 

測(cè)試方式同Jest。

這兩種方式,從設(shè)計(jì)上來(lái)講屬于兩種思路,Spring Data的思路就是將ElasticSearch當(dāng)自家的數(shù)據(jù)倉(cāng)庫(kù)來(lái)管理,直接通過(guò)Java客戶端代碼操作ES;Jest的思路是將ElasticSearch當(dāng)為獨(dú)立的服務(wù)端,自己作為客戶端用兼容性最強(qiáng)的RestFul格式來(lái)與之交互。
個(gè)人比較傾向于Jest方式,第一兼容性好,不需要考慮版本的問(wèn)題。第二,從ElasticSearch本身的設(shè)計(jì)上來(lái)分析,9200是對(duì)外服務(wù)端口,9300是內(nèi)部管理和集群通信端口,請(qǐng)求9200獲取搜索服務(wù)更符合ES的設(shè)計(jì)初衷,不會(huì)影響集群內(nèi)部的通信。
以上比較分析僅代表個(gè)人觀點(diǎn),歡迎大神么交流批評(píng)。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java 中Thread.join()的使用方法

    java 中Thread.join()的使用方法

    這篇文章主要介紹了java 中Thread.join()的使用方法的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • springboot中報(bào)錯(cuò)Invalid character found in the request的解決

    springboot中報(bào)錯(cuò)Invalid character found in 

    這篇文章主要介紹了springboot中報(bào)錯(cuò)Invalid character found in the request的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Java連接MySQL數(shù)據(jù)庫(kù)命令行程序過(guò)程

    Java連接MySQL數(shù)據(jù)庫(kù)命令行程序過(guò)程

    SQL編程包括兩種形式,一種是過(guò)程化編程,主要通過(guò)數(shù)據(jù)庫(kù)交互式工具,通過(guò)存儲(chǔ)過(guò)程、觸發(fā)器、函數(shù)等形式的編程;另一種是嵌入式SQL編程,將SQL語(yǔ)句嵌入到高級(jí)開(kāi)發(fā)語(yǔ)言,完成數(shù)據(jù)的各種操作
    2021-10-10
  • java對(duì)接支付寶支付接口簡(jiǎn)單步驟記錄

    java對(duì)接支付寶支付接口簡(jiǎn)單步驟記錄

    最近項(xiàng)目APP需要接入微信、支付寶支付功能,在分配開(kāi)發(fā)任務(wù)時(shí),聽(tīng)說(shuō)微信支付接口比支付寶支付接口要難實(shí)現(xiàn),這篇文章主要給大家介紹了關(guān)于java對(duì)接支付寶支付接口的簡(jiǎn)單步驟,需要的朋友可以參考下
    2024-05-05
  • SpringBoot使用PageHelper分頁(yè)詳解

    SpringBoot使用PageHelper分頁(yè)詳解

    這篇文章主要介紹了SpringBoot使用PageHelper分頁(yè)詳解,我們?cè)谌魏蔚南到y(tǒng)中,分頁(yè)功能是必不可少的,然而,對(duì)于這個(gè)功能如果有一種快速開(kāi)發(fā)的實(shí)現(xiàn)方式,當(dāng)然可以節(jié)省我們很多的時(shí)間了,接下來(lái),我就給大家基于不同的環(huán)境來(lái)說(shuō)說(shuō)如何使用一個(gè)分頁(yè)插件,需要的朋友可以參考下
    2023-10-10
  • 詳解Java內(nèi)存溢出的幾種情況

    詳解Java內(nèi)存溢出的幾種情況

    這篇文章主要介紹了詳解Java內(nèi)存溢出的幾種情況,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 使用arthas命令redefine實(shí)現(xiàn)Java熱更新(推薦)

    使用arthas命令redefine實(shí)現(xiàn)Java熱更新(推薦)

    今天分享一個(gè)非常重要的命令 redefine ,主要作用是加載外部的 .class 文件,用來(lái)替換 JVM 已經(jīng)加載的類,總結(jié)起來(lái)就是實(shí)現(xiàn)了 Java 的熱更新,感興趣的朋友跟隨小編一起看看吧
    2020-05-05
  • 淺談Java設(shè)計(jì)模式系列-裝飾器模式

    淺談Java設(shè)計(jì)模式系列-裝飾器模式

    這篇文章主要介紹了Java設(shè)計(jì)模式系列-裝飾器模式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • QueryWrapper中or的使用技巧分享

    QueryWrapper中or的使用技巧分享

    在日常的開(kāi)發(fā)工作中,處理數(shù)據(jù)庫(kù)查詢是一個(gè)非常常見(jiàn)的任務(wù),尤其是當(dāng)我們需要在復(fù)雜條件下篩選數(shù)據(jù)時(shí),如何編寫(xiě)高效、簡(jiǎn)潔且可維護(hù)的查詢邏輯顯得尤為重要,本文給大家介紹了QueryWrapper中or的使用技巧,需要的朋友可以參考下
    2024-10-10
  • Java設(shè)計(jì)模式常用原則解析

    Java設(shè)計(jì)模式常用原則解析

    這篇文章主要介紹了Java設(shè)計(jì)模式常用原則解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05

最新評(píng)論

吉木乃县| 清镇市| 开鲁县| 澄江县| 曲麻莱县| 芷江| 安乡县| 道孚县| 漯河市| 云和县| 抚宁县| 巫山县| 长垣县| 嘉兴市| 会宁县| 大安市| 黎平县| 贵港市| 阿拉善左旗| 南和县| 泸溪县| 兴安盟| 都兰县| 丽水市| 麻栗坡县| 上杭县| 神木县| 滕州市| 萨嘎县| 吉林市| 习水县| 柳林县| 蚌埠市| 沅江市| 九寨沟县| 彩票| 伊春市| 尤溪县| 永川市| 洛南县| 镇安县|