Spring Data ElasticSearch 及Kibana調用Restful


什么是spring Data

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

Spring Data常用的功能模塊如下:

spring data commons
spring data JPA
spring data Redis
spring data for Apache Solr
spring data ElasticSearch

什么是Spring Data ElasticSearch 

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

Spring Data ElasticSearch 使用

spring boot實現

引入坐標

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.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>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>

添加application.properties

# ES
#開啟 Elasticsearch 倉庫(默認值:true)
spring.data.elasticsearch.repositories.enabled=true
#默認 9300 是 Java 客戶端的端口。9200 是支持 Restful HTTP 的接口
spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300
#spring.data.elasticsearch.cluster-name Elasticsearch 集群名(默認值: elasticsearch)
#spring.data.elasticsearch.cluster-nodes 集群節點地址列表,用逗號分隔。如果沒有指定,就啟動一個客戶端節點
#spring.data.elasticsearch.propertie 用來配置客戶端的額外屬性
#連接超時的時間
spring.data.elasticsearch.properties.transport.tcp.connect_timeout=120s

創建SpringBoot運行器類

創建實體類

/**
 其中,注解解釋如下:
 @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: 數據類型

 注: 一旦添加了@Filed注解,所有的默認值都不再生效。此外,如果添加了@Filed注解,那么type字段必須指定。
 所以一般不用添加。
 */
@Document(indexName = "blog3",type = "article")
public class Article {

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

增刪改查

test

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ApplicationRun.class)
public class TestSpringDataES {

    @Autowired
    private ArticleService as;

    @Test
    //保存
    public void testSave(){
        Article a = new Article();
        a.setId(1);
        a.setTitle("elasticSearch 3.0版本發布...更新");
        a.setContent("ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用戶能力的全文搜索引擎,基於RESTful web接口");

        as.save(a);
    }
    @Test//修改
    public void testUpdate(){
        Article a = new Article();
        a.setId(1);
        a.setTitle("elasticSearch 3.01版本發布...更新");
        a.setContent("ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用戶能力的全文搜索引擎,基於RESTful web接口");

        as.save(a);
    }

    @Test
    //刪除
    public void testDelete(){
        Article a = new Article();
        a.setId(1);

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

            as.save(a);
        }
    }
    @Test
    //查詢所有保存
    public void testFindAll(){

        Iterable<Article> list = as.findAll();
        for (Article article : list) {
            System.out.println(article);
        }
    }
    @Test
    public void TestFindByPage(){
       // Pageable pageable= PageRequest.of(1,10);
       Pageable pageable= PageRequest.of(1,10, Sort.by(Sort.Order.asc("id;")));
        Page page = as.findByPage(pageable);
        List<Article> list = page.getContent();
        for (Article article : list) {
            System.out.println(article);
        }
    }
    @Test
    //根據title查詢
    public void testFindByTitle(){
        List<Article> list = as.findByTitle("版本");
        for (Article article : list) {
            System.out.println(article);
        }
    }

    @Test
    //根據title查詢
    public void testFindByTitlePage(){
        Pageable pageable=PageRequest.of(0,20,Sort.by(Sort.Order.asc("id")));
        Page page = as.findByTitle("版本", pageable);
        List<Article> list = page.getContent();
        for (Article article : list) {
            System.out.println(article);
        }
    }
}

service

public interface ArticleService {
    //保存
    public void save(Article article);
    //刪除
    public void delete(Article article);

    //查詢
    public Iterable<Article> findAll();

    //分頁查詢
    public Page findByPage(Pageable pageable);

    public List<Article> findByTitle(String title);
    public Page findByTitle(String title,Pageable pageable);
}

impl

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleDao articleDao;
    @Override
    public void save(Article article) {
        articleDao.save(article);
    }

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

    @Override//Sort.by(Sort.Order.asc("id")  根據id排序
    public Iterable<Article> findAll() {
        return articleDao.findAll(Sort.by(Sort.Order.asc("id")));
    }

    @Override
    public Page findByPage(Pageable pageable) {
        return articleDao.findAll(pageable);
    }

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

    @Override
    public Page findByTitle(String title, Pageable pageable) {
        return articleDao.findByTitle(title,pageable);
    }

}

dao

//ElasticsearchRepository<實體類,實體類的主鍵類型> : 提供了CRUD的操作
public interface ArticleDao extends ElasticsearchRepository<Article,Integer> {

    //根據title字段查詢
    public List<Article> findByTitle(String title);

    public Page findByTitle(String title, Pageable pageable);
}

常用查詢命名規則

kibana調用RestAPI

什么是kibana

Kibana是一個基於Node.js的Elasticsearch索引庫數據統計工具,可以利用Elasticsearch的聚合功能,生成各種圖表,如柱形圖,線狀圖,餅圖等。
而且還提供了操作Elasticsearch索引數據的控制台,並且提供了一定的API提示,非常有利於我們學習Elasticsearch的語法。

安裝

因為Kibana依賴於node,需要在windows下先安裝Node.js,然后安裝kibana,最新版本與elasticsearch保持一致,也是5.6.8

解壓即可!

運行

進入安裝目錄下的bin目錄-->雙擊kibana.bat

發現kibana的監聽端口是5601

我們訪問:http://127.0.0.1:5601

控制台

進入之后選擇左側的DevTools菜單,即可進入控制台頁面,在頁面右側,我們就可以輸入請求,訪問Elasticsearch了。

創建索引庫

語法

Elasticsearch采用Rest風格API,因此其API就是一次http請求,你可以用任何工具發起http請求

創建索引的請求格式:
- 請求方式:PUT
- 請求路徑:/索引庫名

使用kibana創建

相當於是省去了elasticsearch的服務器地址

而且還有語法提示,非常舒服。

查看索引數據庫

語法

GET /索引庫名

 

 刪除索引庫

語法

DELETE /索引庫名

類型及映射操作

有了`索引庫`,等於有了數據庫中的`database`。接下來就需要索引庫中的`類型`了,也就是數據庫中的`表`。創建數據庫表需要設置字段約束,索引庫也一樣,
在創建索引庫的類型時,需要知道這個類型下有哪些字段,每個字段有哪些**約束**信息,這就叫做`字段映射(mapping)` 字段的約束我們在學習Lucene中我們都見到過,包括到不限於: - 字段的數據類型 - 是否要存儲 - 是否要索引 - 是否分詞 - 分詞器是什么

創建字段映射

語法

PUT /索引庫名/_mapping/類型名稱
{
  "properties": {
    "字段名": {
      "type": "類型",
      "index": true"store": true"analyzer": "分詞器"
    }
  }
}
  • 類型名稱:就是前面將的type的概念,類似於數據庫中的表 字段名:任意填寫,下面指定許多屬性,例如:

  • type:類型,可以是text、long、short、date、integer、object等

  • index:是否索引,默認為true

  • store:是否存儲,默認為false

  • analyzer:分詞器,這里的ik_max_word即使用ik分詞器

查看映射關系

語法

GET /索引庫名/_mapping

附錄:映射屬性

1)type

Elasticsearch中支持的數據類型非常豐富:

這里說幾個關鍵的:

  • String類型,又分兩種:

    • text:可分詞,不可參與聚合

    • keyword:不可分詞,數據會作為完整字段進行匹配,可以參與聚合

  • Numerical:數值類型,分兩類

    • 基本數據類型:long、interger、short、byte、double、float、half_float

    • 浮點數的高精度類型:scaled_float

      • 需要指定一個精度因子,比如10或100。elasticsearch會把真實值乘以這個因子后存儲,取出時再還原。

  • Date:日期類型

    elasticsearch可以對日期格式化為字符串存儲,但是建議我們存儲為毫秒值,存儲為long,節省空間。

  • Array:數組類型

    • 進行匹配時,任意一個元素滿足,都認為滿足

    • 排序時,如果升序則用數組中的最小值來排序,如果降序則用數組中的最大值來排序

  • Object:對象

{
  name:"Jack",
  age:21,
  girl:{
name: "Rose",
      age:21
  }
}

如果存儲到索引庫的是對象類型,例如上面的girl,會把girl編程兩個字段:girl.name和girl.age

2)index

index影響字段的索引情況。

  • true:字段會被索引,則可以用來進行搜索過濾。默認值就是true

  • false:字段不會被索引,不能用來搜索

index的默認值就是true,也就是說你不進行任何配置,所有字段都會被索引。

但是有些字段是我們不希望被索引的,比如商品的圖片信息,就需要手動設置index為false。

3)store

是否將數據進行額外存儲。

在學習lucene和solr時,我們知道如果一個字段的store設置為false,那么在文檔列表中就不會有這個字段的值,用戶的搜索結果中不會顯示出來。

但是在Elasticsearch中,即便store設置為false,也可以搜索到結果。

原因是Elasticsearch在創建文檔索引時,會將文檔中的原始數據備份,保存到一個叫做_source的屬性中。而且我們可以通過過濾_source來選擇哪些要顯示,哪些不顯示。

而如果設置store為true,就會在_source以外額外存儲一份數據,多余,因此一般我們都會將store設置為false,事實上,store的默認值就是false。

4)boost

權重,新增數據時,可以指定該數據的權重,權重越高,得分越高,排名越靠前。

一次創建索引庫和類型

put /索引庫名
{
    "settings":{
        "索引庫屬性名":"索引庫屬性值"
    },
    "mappings":{
        "類型名":{
            "properties":{
                "字段名":{
                    "映射屬性名":"映射屬性值"
                }
            }
        }
    }
}

文檔操作

新增文檔

通過POST請求,可以向一個已經存在的索引庫中添加文檔數據。

POST /索引庫名/類型名
{
    "key":"value"
}

另外,需要注意的是,在響應結果中有個_id字段,這個就是這條文檔數據的唯一標示,以后的增刪改查都依賴這個id作為唯一標示。

可以看到id的值為:r9c1KGMBIhaxtY5rlRKv,這里我們新增時沒有指定id,所以是ES幫我們隨機生成的id。

查看文檔

根據rest風格,新增是post,查詢應該是get,不過查詢一般都需要條件,這里我們把剛剛生成數據的id帶上。

通過kibana查看數據:

GET /test1/goods/r9c1KGMBIhaxtY5rlRKv

新增文檔並自定義id

POST /索引庫名/類型/id值
{
    ...
}
示例:
POST /test1/goods/2
{
    "title":"大米手機",
    "images":"http://image.leyou.com/12479122.jpg",
    "price":2899.00
}

修改數據

把剛才新增的請求方式改為PUT,就是修改了。不過修改必須指定id,

  • id對應文檔存在,則修改

  • id對應文檔不存在,則新增

比如,我們把使用id為3,不存在,則應該是新增:

PUT /test1/goods/3
{
    "title":"超米手機",
    "images":"http://image.leyou.com/12479122.jpg",
    "price":3899.00,
    "stock": 100,
    "saleable":true
}

我們再次執行剛才的請求,不過把數據改一下:

PUT /test1/goods/3
{
    "title":"超大米手機",
    "images":"http://image.leyou.com/12479122.jpg",
    "price":3299.00,
    "stock": 100,
    "saleable":true
}

刪除數據

刪除使用DELETE請求,同樣,需要根據id進行刪除:

語法

DELETE /索引庫名/類型名/id值

查詢

  • 基本查詢

  • _source過濾

  • 結果過濾

  • 高級查詢

  • 排序

基本語法

GET /索引庫名/_search
{
    "query":{
        "查詢類型":{
            "查詢條件":"查詢條件值"
        }
    }
}

這里的query代表一個查詢對象,里面可以有不同的查詢屬性

  • 查詢類型:

    • 例如:match_all, matchterm , range 等等

  • 查詢條件:查詢條件會根據類型的不同,寫法也有差異

查詢所有(match_all)

GET /test1/_search
{
    "query":{
        "match_all": {}
    }
}
  • query:代表查詢對象

  • match_all:代表查詢所有

匹配查詢

我們先加入一條數據

PUT /test1/goods/3
{
    "title":"小米電視4A",
    "images":"http://image.leyou.com/12479122.jpg",
    "price":3899.00
}
  • or關系

match類型查詢,會把查詢條件進行分詞,然后進行查詢,多個詞條之間是or的關系

GET /test1/_search
{
    "query":{
        "match":{
            "title":"小米電視"
        }
    }
}

 

  • and關系

某些情況下,我們需要更精確查找,我們希望這個關系變成and,可以這樣做:

GET /goods/_search
{
    "query":{
        "match":{
            "title":{"query":"小米電視","operator":"and"}
        }
    }
}

詞條匹配

term 查詢被用於精確值 匹配,這些精確值可能是數字、時間、布爾或者那些未分詞的字符串

GET /test1/_search
{
    "query":{
        "term":{
            "price":2699.00
        }
    }
}

模糊查詢(fuzzy)

我們新增一個商品:

POST /test1/goods/4
{
    "title":"apple手機",
    "images":"http://image.leyou.com/12479122.jpg",
    "price":6899.00
}

fuzzy 查詢是 term 查詢的模糊等價。它允許用戶搜索詞條與實際詞條的拼寫出現偏差,但是偏差的編輯距離不得超過2:

GET /test1/_search
{
  "query": {
    "fuzzy": {
      "title": "appla"
    }
  }
}

上面的查詢,也能查詢到apple手機

我們可以通過fuzziness來指定允許的編輯距離:

GET /test1/_search
{
  "query": {
    "fuzzy": {
        "title": {
            "value":"appla",
            "fuzziness":1
        }
    }
  }
}

排序

sort 可以讓我們按照不同的字段進行排序,並且通過order指定排序的方式

GET /test1/_search
{
"query": {
"match": {
"title": "小米手機"
}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}

分頁

elasticsearch的分頁與mysql數據庫非常相似,都是指定兩個值:

  • from:開始位置

  • size:每頁大小

GET /test1/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "price": {
        "order": "asc"
      }
    }
  ],
  "from": 3,
  "size": 3
}

高亮

高亮原理:

  • 服務端搜索數據,得到搜索結果

  • 把搜索結果中,搜索關鍵字都加上約定好的標簽

  • 前端頁面提前寫好標簽的CSS樣式,即可高亮

elasticsearch中實現高亮的語法比較簡單:

GET /test1/_search
{
  "query": {
    "match": {
      "title": "手機"
    }
  },
  "highlight": {
    "pre_tags": "<em>",
    "post_tags": "</em>", 
    "fields": {
      "title": {}
    }
  }
}

在使用match查詢的同時,加上一個highlight屬性:

  • pre_tags:前置標簽

  • post_tags:后置標簽

  • fields:需要高亮的字段

    • title:這里聲明title字段需要高亮,后面可以為這個字段設置特有配置,也可以空.

 


免責聲明!

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



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