Spring Boot中集成Elasticsearch有幾種方式

  • 通過 REST Client 方式 集成 ES 7.*

    <dependency>
      <groupId>org.elasticsearch</groupId>
      <artifactId>elasticsearch</artifactId>
      <version>7.1.1</version>
    </dependency>
    <dependency>
      <groupId>org.elasticsearch.client</groupId>
      <artifactId>elasticsearch-rest-client</artifactId>
      <version>7.1.1</version>
    </dependency>
    <dependency>
      <groupId>org.elasticsearch.client</groupId>
      <artifactId>elasticsearch-rest-high-level-client</artifactId>
      <exclusions>
        <exclusion>
          <groupId>org.elasticsearch</groupId>
          <artifactId>elasticsearch</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.elasticsearch.client</groupId>
          <artifactId>elasticsearch-rest-client</artifactId>
        </exclusion>
      </exclusions>
      <version>7.1.1</version>
    </dependency>
    
    elasticSearch.host = 你的服務器地址
    elasticSearch.port = 9200
    elasticSearch.client.connectNum=10
    elasticSearch.client.connectPerRoute=50
    
  • 通過 spring-data-elasticsearch 方式 ,SpringBoot 2.2.0.RELEASE 才兼容elasticsearch 7.x , SpringBoot, spring-data-elasticsearch, ES 三者 版本對應關係 - 驗證可行

    • 首先引進maven依賴
    <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.2.2.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <elasticsearch.version>7.4.2</elasticsearch.version>
     <spring.data.elasticsearch.version>3.2.3.RELEASE</spring.data.elasticsearch.version>
    </properties>
    <dependencies>
      <dependency>
        <groupId>org.elasticsearch</groupId>
        <artifactId>elasticsearch</artifactId>
        <version>${elasticsearch.version}</version>
      </dependency>
      <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>transport</artifactId>
        <version>${elasticsearch.version}</version>
      </dependency>
      <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-client</artifactId>
        <version>${elasticsearch.version}</version>
      </dependency>
      <dependency>
        <groupId>org.elasticsearch.plugin</groupId>
        <artifactId>transport-netty4-client</artifactId>
        <version>${elasticsearch.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-elasticsearch</artifactId>
        <version>${spring.data.elasticsearch.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
      </dependency>
    
    • 配置 properties
    spring.data.elasticsearch.cluster-name=my-application
    #配置9200是通過HTTP連接的端口,9300是TCP連接的端口
    spring.data.elasticsearch.cluster-nodes=192.168.1.134:9300
    
    @Repository
    public interface CommodityRepository extends ElasticsearchRepository<CommodityDomain, String>, Serializable {
    }
    
    // CommodityRepository 支持的方法
    public interface ElasticsearchRepository <T, ID> extends org.springframework.data.elasticsearch.repository.ElasticsearchCrudRepository<T,ID> {
        <S extends T> S index(S s);
        <S extends T> S indexWithoutRefresh(S s);
        Iterable<T> search(QueryBuilder queryBuilder);
        Page<T> search(QueryBuilder queryBuilder, Pageable pageable);
        Page<T> search(SearchQuery searchQuery);
        Page<T> searchSimilar(T t, String[] strings, Pageable pageable);
        void refresh();
        java.lang.Class<T> getEntityClass();
    }
    
    public interface CrudRepository <T, ID> extends org.springframework.data.repository.Repository<T,ID> {
        <S extends T> S save(S s);
        <S extends T> Iterable<S> saveAll(java.lang.Iterable<S> iterable);
        java.util.Optional<T> findById(ID id);
        boolean existsById(ID id);
        java.lang.Iterable<T> findAll();
        java.lang.Iterable<T> findAllById(Iterable<ID> iterable);
        long count();
        void deleteById(ID id);
        void delete(T t);
        void deleteAll(Iterable<? extends T> iterable);
        void deleteAll();
    }
    
    • 使用 CommodityRepository
    @Autowired
    CommodityRepository commodityRepository;
    // 新增一個索引
    String documentId = "123456";
    CommodityDomain sampleEntity1 = new CommodityDomain();
    sampleEntity1.setId(documentId);
    sampleEntity1.setMessage("some message");
    repository.save(sampleEntity1);
    // 批量新增索引
    repository.saveAll(list);
    
    @Autowired
    ElasticSearchTemplate elasticSearchTemplate;
    
    String documentId = "123456";
    SampleEntity sampleEntity = new SampleEntity();
    sampleEntity.setId(documentId);
    sampleEntity.setMessage("some message");
    // 一次只新增一個 索引
    IndexQuery indexQuery = new IndexQueryBuilder()
      .withId(sampleEntity.getId())
      .withObject(sampleEntity).build();
    elasticsearchTemplate.index(indexQuery);
    
    // clazz 索引 不存在
    if(!elasticsearchTemplate.indexExists(clazz)) {
      elasticsearchTemplate.createIndex(clazz);
      elasticsearchTemplate.putMapping(clazz);
    }
    // 批量新增索引,速度非常快
    elasticsearchTemplate.bulkIndex(queries);
    
    // 單字符串全文查詢
    SearchQuery searchQuery = new NativeSearchQueryBuilder()
      .withQuery(queryStringQuery("浣溪沙"))
      .withPageable(pageable).build();
    // 查詢某個字段中模糊包含目標字符串,使用matchQuery
    earchQuery searchQuery = new NativeSearchQueryBuilder()
      .withQuery(matchQuery("content", "落日熔金"))
      .withPageable(pageable).build();
    //PhraseMatch查詢,短語匹配 : match_phrase查詢首先解析查詢字符串來產生一個詞條列表。然後會搜索所有的詞條,但只保留包含了所有搜索詞條的文檔,並且詞條的位置要鄰接。一個針對短語“中華共和國”的查詢不會匹配“中華人民共和國”,因爲沒有含有鄰接在一起的“中華”和“共和國”詞條。
    SearchQuery searchQuery = new NativeSearchQueryBuilder()
      .withQuery(matchPhraseQuery("content", "落日熔金"))
      .withPageable(pageable).build();
    // Term 查詢: 這個是最嚴格的匹配,屬於低級查詢,不進行分詞。我們可以用這個來做那種需要==查詢的操作,當傳userId=1時,會查詢出來所有userId爲1的集合。通常情況下,我們不會使用term查詢,絕大部分情況我們使用ES的目的就是爲了使用它的分詞模糊查詢功能。而term一般適用於做過濾器filter的情況,譬如我們去查詢title中包含“浣溪沙”且userId=1時,那麼就可以用termQuery("userId", 1)作爲查詢的filter
    SearchQuery searchQuery = new NativeSearchQueryBuilder()
      .withQuery(termQuery("userId", 1))
      .withPageable(pageable).build();
    // multi_match多個字段匹配某字符串: 如果我們希望title,content兩個字段去匹配某個字符串,只要任何一個字段包括該字符串即可,就可以使用multimatch
    SearchQuery searchQuery = new NativeSearchQueryBuilder()
      .withQuery(multiMatchQuery(title, "title", "content"))
      .withPageable(pageable).build();
    // 完全包含查詢 : 我們輸入“我天”時,ES會把分詞後所有包含“我”和“天”的都查詢出來,如果我們希望必須是包含了兩個字的才能被查詢出來,那麼我們就需要設置一下Operator ; 無論是matchQuery,multiMatchQuery,queryStringQuery等,都可以設置operator。默認爲Or,設置爲And後,就會把符合包含所有輸入的才查出來
    SearchQuery searchQuery = new NativeSearchQueryBuilder()
      .withQuery(matchQuery("title", title)
                 .operator(MatchQueryBuilder.Operator.AND))
      .build();
    // minimumShouldMatch可以用在match查詢中,設置最少匹配了多少百分比的能查詢出來 
    SearchQuery searchQuery = new NativeSearchQueryBuilder()
      .withQuery(matchQuery("title", title)
                 .operator(MatchQueryBuilder.Operator.AND)
                 .minimumShouldMatch("75%")
                ).build();
    // 合併查詢 : 即boolQuery,可以設置多個條件的查詢方式。它的作用是用來組合多個Query,有四種方式來組合,must,mustnot,filter,should。
    // must代表返回的文檔必須滿足must子句的條件,會參與計算分值;
    // filter代表返回的文檔必須滿足filter子句的條件,但不會參與計算分值;
    // should代表返回的文檔可能滿足should子句的條件,也可能不滿足,有多個should時滿足任何一個就可以, 通過minimum_should_match設置至少滿足幾個。
    // mustnot 代表必須不滿足子句的條件。
    SearchQuery searchQuery = new NativeSearchQueryBuilder()
      .withQuery(boolQuery()   // title包含“XXX”,且userId=“1”
                 .must(termQuery("userId", userId))   
                 .should(rangeQuery("weight").lt(weight)) // 且weight最好小於5的結果
                 .must(matchQuery("title", title))
                ).build();
    elasticSearchTemplate.queryForList(searchQuery, Post.class);
    
    // Query和Filter的區別
    // 1、查詢:是在使用query進行查詢時的執行環境,比如使用search的時候。在查詢上下文中,查詢會回答這個問題——“這個文檔是否匹配這個查詢,它的相關度高麼?”ES中索引的數據都會存儲一個_score分值,分值越高就代表越匹配。即使lucene使用倒排索引,對於某個搜索的分值計算還是需要一定的時間消耗。
    // 2、過濾器:在使用filter參數時候的執行環境,比如在bool查詢中使用Must_not或者filter. 在過濾器上下文中,查詢會回答這個問題——“這個文檔是否匹配?” 它不會去計算任何分值,也不會關心返回的排序問題,因此效率會高一點。另外,經常使用過濾器,ES會自動的緩存過濾器的內容,這對於查詢來說,會提高很多性能。
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章