1. 程式人生 > >ElasticSearch的查詢(二)

ElasticSearch的查詢(二)

一、Query String search

  新增測試資料

PUT test_search
{
  "mappings": {
    "test_type": {
      "properties": {
        "dname": {
          "type": "text",
          "analyzer": "standard"
        },
        "ename": {
          "type": "text",
          "analyzer": "standard"
        },
        "eage": {
          "type": "long"
        },
        "hiredate": {
          "type": "date"
        },
        "gender": {
          "type": "keyword"
        }
      }
    }
  }
}

POST test_search/test_type/_bulk
{"index":{}}
{"dname":"Sales Department","ename":"張三","eage":20,"hiredate":"2019-01-01","gender":"男性"}
{"index":{}}
{"dname":"Sales Department","ename":"李四","eage":21,"hiredate":"2019-02-01","gender":"男性"}
{"index":{}}
{"dname":"Development Department","ename":"王五","eage":23,"hiredate":"2019-01-03","gender":"男性"}
{"index":{}}
{"dname":"Development Department","ename":"趙六","eage":26,"hiredate":"2018-01-01","gender":"男性"}
{"index":{}}
{"dname":"Development Department","ename":"韓梅梅","eage":24,"hiredate":"2019-03-01","gender":"女性"}
{"index":{}}
{"dname":"Development Department","ename":"錢虹","eage":29,"hiredate":"2018-03-01","gender":"女性"}
View Code

  search的引數都是類似http請求頭中的字串引數提供搜尋條件的

  GET [/index_name/type_name/]_search[?parameter_name=parameter_value&...]

1,全搜尋

  timeout引數:是超時時長定義。代表每個節點上的每個shard執行搜尋時最多耗時多久。不會影響響應的正常返回。只會影響返回響應中的資料數量。

  如:索引a中,有10億資料。儲存在5個shard中,假設每個shard中2億資料,執行全資料搜尋的時候,需要耗時1000毫秒。定義timeout為10毫秒,代表的是shard執行10毫秒,搜尋出多少資料,直接返回。

  在商業專案中,是禁止全資料搜尋的。必須指定搜尋的索引,型別和關鍵字。如果沒有指定索引或型別,則代表開發目的不明確,需要重新做用例分析。如果沒有關鍵字,稱為索引內全搜尋,也叫魔鬼搜尋。

  GET [索引名/型別名/]_search?timeout=10ms

結果返回:

{
  "took": 144, #請求耗時多少毫秒
  "timed_out": false, #是否超時。預設情況下沒有超時機制,也就是客戶端等待ElasticSearch搜尋結束(無論執行多久),提供超時機制的話,ElasticSearch則在指定時長內處理搜尋,在指定時長結束的時候,將搜尋的結果直接返回(無論是否搜尋結束)。指定超時的方式是傳遞引數,引數單位是:毫秒-ms。秒-s。分鐘-m。
  "_shards": {
    "total": 1, #請求傳送到多少個shard上
    "successful": 1,#成功返回搜尋結果的shard
    "skipped": 0, #停止服務的shard
    "failed": 0 #失敗的shard
  },
  "hits": {
    "total": 1, #返回了多少結果
    "max_score": 1, #搜尋結果中,最大的相關度分數,相關度越大分數越高,_score越大,排位越靠前。
    "hits": [ #搜尋到的結果集合,預設查詢前10條資料。
      {
        "_index": "test_index", #資料所在索引
        "_type": "my_type", #資料所在型別
        "_id": "1", #資料的id
        "_score": 1, #資料的搜尋相關度分數
        "_source": { # 資料的具體內容。
          "field": "value"
        }
      }
    ]
  }
}

2,multi index搜尋

  所謂的multi-index就是從多個index中搜索資料。相對使用較少,只有在複合資料搜尋的時候,可能出現。一般來說,如果真使用複合資料搜尋,都會使用_all。

  如:搜尋引擎中的無條件搜尋。(現在的應用中都被遮蔽了。使用的是預設搜尋條件,執行資料搜尋。 如: 電商中的搜尋框預設值, 搜尋引擎中的類別)

  無條件搜尋,在搜尋應用中稱為“魔鬼搜尋”,代表的是,搜尋引擎會執行全資料檢索,效率極低,且對資源有非常高的壓力。

GET _search #搜尋所有的索引
GET 索引名1,索引名2/_search # 搜尋多個index中的資料
GET 索引名/型別名/_search # 所屬一個index中type的資料
GET prefix_*/_search # 萬用字元搜尋
GET *_suffix/_search
GET 索引名1,索引名2/型別名/_search # 搜尋多個index中type的資料
GET _all/_search  # _all代表所有的索引

3,條件搜尋

  query string search 搜尋是通過HTTP請求的請求頭傳遞引數的,預設的HTTP請求頭字符集是ISO-8859-1,請求頭傳遞中文會有亂碼。

  GET 索引名/_search?q=欄位名:搜尋條件

4,分頁搜尋

  預設情況下,ElasticSearch搜尋返回結果是10條資料。從第0條開始查詢

  GET 索引名/_search?from=0&size=10 # from 從第幾行開始查詢,行號從0開始。

5,+/-搜尋

語法:

GET 索引名/_search?q=欄位名:條件   #不加+/-預設使用的是+
GET 索引名/_search?q=+欄位名:條件
GET 索引名/_search?q=-欄位名:條件

  + :和不定義符號含義一樣,就是搜尋指定的欄位中包含keywords的資料,預設。

  - : 與+符號含義相反,就是搜尋指定的欄位中不包含keywords的資料。

6,排序

  GET 索引名/_search?sort=欄位名:排序規則

案例:

GET test_search/_search?sort=eage:asc
GET test_search/_search?sort=eage:desc
GET test_search/_search?sort=gender:desc,eage:desc

二、DSL

  DSL - Domain Specified Language , 特殊領域的語言。

  請求引數是請求體傳遞的。在ElasticSearch中,請求體的字符集預設為UTF-8。

語法:

GET 索引名/_search
{
   "command":{ "parameter_name" : "parameter_value"}
}

1,查詢所有

GET 索引名/_search
{
   "query" : { "match_all" : {} }
}

2,match search

  全文檢索。要求查詢條件拆分後的任意詞條與具體資料匹配就算搜尋結果。

GET 索引名/_search
{
  "query": {
    "match": {
      "欄位名": "搜尋條件"
    }
  }
}

3,phrase search

  短語檢索。要求查詢條件必須和具體資料完全匹配才算搜尋結果。其特徵是:1-搜尋條件不做任何分詞解析;2-在搜尋欄位對應的倒排索引(正排索引)中進行精確匹配,不再是簡單的全文檢索。

GET 索引名/_search
{
  "query": {
    "match_phrase": {
      "欄位名": "搜尋條件"
    }
  }
}

4,range

  範圍檢索

GET 索引名/型別名/_search
{
  "query" : {
    "range" : {
      "欄位名" : {
        "gt" : 搜尋條件1, 
        "lte" : 搜尋條件2
      }
    }
  }
}    

5,term

  片語搜尋。忽略搜尋條件分詞,在ElasticSearch倒排索引中進行精確匹配。

GET 索引名/型別名/_search
{
  "query" : {
    "term" : {
      "欄位名": "搜尋條件"
    }
  }
}

GET 索引名/型別名/_search
{
  "query" : {
    "terms" : {
      "欄位名": ["搜尋條件1", "搜尋條件2"]
    }
  }
}
  • term是將傳入的文字原封不動地(不分詞)拿去查詢。
  • match會對輸入進行分詞處理後再去查詢,部分命中的結果也會按照評分由高到低顯示出來。
  • match_phrase是按短語查詢,只有存在這個短語的文件才會被顯示出來。會對傳入的文字進行分詞,但是必須完全匹配並且順序相同。

6,多條件must、should、must_not

  • must陣列中的多個條件必須同時滿足
  • must_not陣列中的多個條件必須都不滿足
  • should陣列中的多個條件有任意一個滿足即可。
GET 索引名/型別名/_search
{
  "query": {
    "bool": {
      "must": [ #陣列中的多個條件必須同時滿足
        {
          "range": {
            "欄位名": {
              "lt": 條件
            }
          }
        }
      ],
      "must_not":[ #陣列中的多個條件必須都不滿足
        {
          "match": {
            "欄位名": "條件"
          }
        },
        {
          "range": {
            "欄位名": {
              "gte": "搜尋條件"
            }
          }
        }
      ],
      "should": [# 陣列中的多個條件有任意一個滿足即可。
        {
          "match": {
            "欄位名": "條件"
          }
        },
        {
          "range": {
            "欄位名": {
              "gte": "搜尋條件"
            }
          }
        }
      ]
    }
  }
}

7,排序

  在ElasticSearch的搜尋中,預設是使用相關度分數實現排序的。可以通過搜尋語法實現定製化排序。

GET 索引名/型別名/_search
{
  "query": {
    [搜尋條件]
  },
  "sort": [
    {
      "欄位名1": {
        "order": "asc"
      }
    },
    {
      "欄位名2": {
        "order": "desc"
      }
    }
  ]
}

  注意:在ElasticSearch中,如果使用text型別的欄位作為排序依據,會有問題。ElasticSearch需要對text型別欄位資料做分詞處理。如果使用text型別欄位做排序,ElasticSearch給出的排序結果未必友好,畢竟分詞後,先使用哪一個單詞做排序都是不合理的。所以ElasticSearch中預設情況下不允許使用text型別的欄位做排序,如果需要使用字串做結果排序,則可使用keyword型別欄位作為排序依據,因為keyword欄位不做分詞處理。

8,分頁

  DSL分頁也是使用from和size實現的。

GET 索引名稱/_search
{
  "query":{
    "match_all":{}
},
"from": 起始下標,
"size": 查詢記錄數
}

9,高亮

  在搜尋中,經常需要對搜尋關鍵字做高亮顯示,這個時候就可以使用highlight語法。

GET 索引名/_search
{
  "query": {
    "match": {
      "欄位名": "條件"
    }
  },
  "highlight": {
    "fields": {
      "要高亮顯示的欄位名": {
        "fragment_size": 5, #每個分段長度,預設20
        "number_of_fragments": 1 #返回多少個分段,預設3
      }
    },
    "pre_tags": ["字首"], 
    "post_tags": ["字尾"] 
  }
}

案例:

GET test_search/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "dname": "Development department"
          }
        },
        {
          "match": {
            "gender": "男性"
          }
        }
      ]
    }
  },
  "highlight": {
    "fields": {
      "dname": {
        "fragment_size": 20,
        "number_of_fragments": 1
      },
      "gender": {
        "fragment_size": 20,
        "number_of_fragments": 1
      }
    },
    "pre_tags": [
      "<span style='color:red'>"
    ],
    "post_tags": [
      "</span>"
    ]
  },
  "from": 2,
  "size": 2
}

10,聚合查詢

語法:

"aggs": {
    "NAME": {# 指定結果的名稱
      "AGG_TYPE": {# 指定具體的聚合方法,
        TODO: # 聚合體內製定具體的聚合欄位
      }
    },
    "NAME": {# 指定結果的名稱
      "AGG_TYPE": {# 指定具體的聚合方法,
        TODO: # 聚合體內製定具體的聚合欄位
      }
    }
 }

  

三、SpringDataElasticsearch

  原始碼:cloud-es

1,新增pom檔案

<dependency>
    <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2,修改applicaiton配置

#低版本使用5.x,注意使用的springdata的版本與es是否對應
spring.data.elasticsearch.cluster-name=es5-cluster
spring.data.elasticsearch.cluster-nodes= hadoop208:9300,hadoop209:9300
#高版本使用6.x
spring.elasticsearch.rest.uris=http://hadoop208:9200,http://hadoop209:9200

3,建立實體

  案例:Item物件

  • @Document指定實體類和索引對應關係@Id 指定主鍵
    • indexName:索引名稱
    • type: 索引型別(不加會給預設,es7之後刪除)
    • shards: 主分片數量,預設5
    • replicas:複製分片數量,預設1
  • @Field指定普通屬性
    • type: 對應Elasticsearch中屬性型別。使用FiledType列舉可以快速獲取。測試發現沒有type屬性可能出現無法自動建立型別問題,所以一定要有type屬性。
    • text型別能被分詞
    • keywords不能被分詞
    • index: 是否建立索引。作為搜尋條件時index必須為true
    • analyzer:指定分詞器型別。
    • fielddata:指定是否為text型別欄位建立正向索引。預設為false,設定為true則可以使用此欄位排序。

4,使用方式

  案例:ItemTest

&n