springboot與檢索(elasticsearch)

springboot與檢索(elasticsearch)

一、檢索

Elasticsearch是一個分佈式搜索服務,提供Restful API,底層基於Lucene,採用多shard(分片)的方式保證數據安全,並且提供自動resharding的功能,github等大型的站點也是採用了ElasticSearch作爲其搜索服務,

  • 在docker中安裝 啓動elasticsearch 容器

啓動 elasticsearch容器:

# 拉取鏡像
# docker pull elasticsearch:2.4.0

# 啓動 elasticsearch 容器
# docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -di -p 9200:9200 -p 9300:9300 --name es01 elasticsearch:2.4.0

若開啓了防火牆,記得開放 9200 和 9300 端口

查看已經開放的端口
# firewall-cmd --list-ports
    
開啓端口
# firewall-cmd --zone=public --add-port=80/tcp --permanent  
    
# –zone #作用域
# –add-port=80/tcp #添加端口,格式爲:端口/通訊協議
# –permanent #永久生效,沒有此參數重啓後失效
    
重啓firewall  
# firewall-cmd --reload  

啓動容器後:在瀏覽器中輸入 elasticsearch 安裝的容器所在的服務器的 ip:9200

  • elasticsearch 通過restful api 的方式來操作:

    將HTTP命令由puT改爲GET可以用來檢索文檔,同樣的,可以使用DELETE命令來刪除文檔,以及使用HEAD指令來檢查文檔是否存在。如果想更新已存在的文檔,只需再次PUT。

    例:

    PUT ip:9200/megacorp/employee/1

    {
        "username":"superzheng",
        "password":"密碼"
    }
    

    GET ip:9200/megacorp/employee/1

    或者搜索:

    GET ip:9200/megacorp/employee/_search?q=last_name:Smith

    通過json數據體搜索:

    POST ip:9200/megacorp/employee/_search

    # match 爲模糊匹配 last_name 爲字段  Smith爲匹配值
    # 將 match 改爲 match_phrase 爲完全匹配
    {
        "query":{
    		"match":{
    			"last_name":"Smith"
            }
        }
    }
    

    通過json數據體高級搜索:

    POST ip:9200/megacorp/employee/_search

    # 匹配 姓名爲 smith 的並且年齡必須大於 30{
    	"query":{
    		"bool":{
                "must":{
    				"match":{
    					"1ast_name":"Smith"
    				}
    			},
    			"filter":{
    				"range":{
    					"age":{"gt":30}
                    }
                }
            }
        },
        "highlight":{
    		"fields":{
    			"about" : {}
            }
        }
    }
    

二、在項目中操作 elasticsearch

  • 以 jest 的方式操作 elasticsearch

導入 jest 需要的jar 包:

<!-- https://mvnrepository.com/artifact/io.searchbox/jest
            以 jest 的方式操作 elasticsearch
        -->
        <dependency>
            <groupId>io.searchbox</groupId>
            <artifactId>jest</artifactId>
            <version>5.3.3</version>
        </dependency>

實體類(用到了 lombok)

@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class Article {

    /**
     * 標識這是主鍵
     */
    @JestId
    private Long id;

    private String author;

    private String title;

    private String content;
}
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Document(indexName = "mesmile", type = "book") // indexName 索引名  type 類型
public class Book {


    private Long id;

    private String bookName;

    private String author;

}

測試elasticsearch 的存儲與搜索

package cn.mesmile.springboot.elastic;

import cn.mesmile.springboot.elastic.domain.Article;
import cn.mesmile.springboot.elastic.domain.Book;
import cn.mesmile.springboot.elastic.repository.BookRepository;
import io.searchbox.client.JestClient;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ElasticApplicationTests {

    /**
     *  對 elasticsearch 進行操作有兩種方式
     *
     *      方式 ① jest 的方式
     *             方式① 需要導入 jar 包
     *          <!-- https://mvnrepository.com/artifact/io.searchbox/jest
     *             以 jest 的方式操作 elasticsearch
     *         -->
     *         <dependency>
     *             <groupId>io.searchbox</groupId>
     *             <artifactId>jest</artifactId>
     *             <version>5.3.3</version>
     *         </dependency>
     *
     *      方式 ② springdataes 的方式,需要繼承 ElasticsearchRepository<T,D> 接口  T爲實體類,D爲實體類主鍵類型
     *
     *          注意 springboot 版本 和 elasticsearch 版本 匹配
     *          【記得沒錯此依賴只針對的是6.0版本以上ES,6.0版本以下ES不適用於SpringBoot的依賴。】
     *           這裏選用的是【 springboot:1.5.9         elasticsearch:2.4.0】
     */

    @Autowired
    private JestClient jestClient;

    @Autowired
    private BookRepository bookRepository;

    /**
     *  jest 的方式對 elasticsearch 進行展示
     */
    @Test
    public void contextLoads() {
        Article article = Article.builder()
                .id(1L)
                .author("superzheng")
                .title("通知")
                .content("今天項目上線了")
                .build();

        // 構建一個索引               保存什麼         保存在哪      類型是什麼
        Index index = new Index.Builder(article).index("mesmile").type("news").build();

        try {
            // 執行
            // 執行成功後再網址驗證查詢 ip:9200/mesmile/news/1
            jestClient.execute(index);
            /*
                結果如下:
                {
                    "_index": "mesmile",
                    "_type": "news",
                    "_id": "1",
                    "_version": 1,
                    "found": true,
                    "_source": {
                        "id": 1,
                        "author": "superzheng",
                        "title": "通知",
                        "content": "今天項目上線了"
                    }
                }
             */
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Test
    public void testSearch() {

        String json = "{\n" +
                "    \"query\":{\n" +
                "\t\t\"match\":{\n" +
                "\t\t\t\"content\":\"項目\"\n" +
                "        }\n" +
                "    }\n" +
                "}";
        // 構建搜索
        Search search = new Search.Builder(json).addIndex("mesmile").addType("news").build();

        try {
            // 執行搜索
            SearchResult result = jestClient.execute(search);

            // 生成 json 字符串
            System.out.println(result.getJsonString());

            // 搜索並轉換成我們需要的
            Article sourceAsObject = result.getSourceAsObject(Article.class,true);
            System.out.println(sourceAsObject);

        } catch (IOException e) {
            e.printStackTrace();
        }
        /*
        {
            "took": 58,
            "timed_out": false,
            "_shards": {
                "total": 5,
                "successful": 5,
                "skipped": 0,
                "failed": 0
            },
            "hits": {
                "total": 1,
                "max_score": 0.5716521,
                "hits": [{
                    "_index": "mesmile",
                    "_type": "news",
                    "_id": "1",
                    "_score": 0.5716521,
                    "_source": {
                        "id": 1,
                        "author": "superzheng",
                        "title": "通知",
                        "content": "今天項目上線了"
                    }
                }]
            }
        }
         */
    }

    /**
     *  repository的方式
     */
    @Test
    public void testBook() {
        Book book = Book.builder()
                .id(1L)
                .bookName("紅樓夢")
                .author("曹雪芹")
                .build();
        // 存儲數據
        bookRepository.index(book);
    }

    @Test
    public void testSearchLike() {
        // 模糊查詢
        List<Book> data = bookRepository.findByBookNameLike("樓");
        data.forEach(System.out::println);
    }

}



三、出現異常

NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{BCBUirWrTIy-RJ5ZnNj3xA}{40.100.00.200}{40.100.00.200:9300}]
]
    
<!-- springboot data elasticsearch 支持
            【記得沒錯此依賴只針對的是6.0版本以上ES,6.0版本以下ES不適用於SpringBoot的依賴。】
             這裏選用的是【 springboot:1.5.9         elasticsearch:2.4.0-->
  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  </dependency>
    

項目配置文件

# 9200作爲Http協議,主要用於外部通訊
#9300作爲Tcp協議,jar之間就是通過tcp協議通訊
#ES集羣之間是通過9300進行通訊

#9200 是ES節點與外部通訊使用的端口。它是http協議的RESTful接口(各種CRUD操作都是走的該端口,如查詢:http://localhost:9200/user/_search)。
#9300是ES節點之間通訊使用的端口。它是tcp通訊端口,集羣間和TCPclient都走的它。(java程序中使用ES時,在配置文件中要配置該端口)

spring:
  elasticsearch:
    jest:
      uris: http://40.100.00.200:9200
  data:
    elasticsearch:
      cluster-nodes: 40.100.00.200:9300
      # 默認名稱是 elasticsearch 通過 ip:9200 查看
      cluster-name: elasticsearch
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章