天天看點

ElasticSearch基礎知識--檢索文檔

一、面向文檔

二、Json

三、索引

四、檢索文檔

1、簡單搜尋

2、搜尋全部商品資訊

3、query string 4、用DSL語句查詢 5、全文搜尋

6、短語搜尋

7、高亮搜尋(highlight)

8、聚合

一、面向文檔

1、假如們在資料庫中有一張商品表,當我想通過一個商品名稱去模糊比對的時候,那麼的的sql可能是這樣的

select a.* from product a where a.productName like %xxx%
           

那假如我還有一張表商品的型号表(一個商品有多個型号也就是1對多的關系)

我就必須使用left join 然後将商品型号表作為一個list放入到對應的商品下面,組成json資料類似于這樣

{
    "productName": "商品名稱",
    "productCode": "商品編号",
    "model": [
        {
            "name": "型号1"
        },
        {
            "name": "型号2"
        }
    ]
}
           

我們知道商品表和商品型号表都是一行和列的資料結構存儲在資料庫中的,是以,每次進行查詢的時候都必須進行sql查詢和json資料的拼裝等工作。 如果使用Elasticsearch就不必如此。 Elasticsearch是面向文檔(document oriented)的,這意味着它可以存儲整個對象或文檔(document)。然而它不僅僅是存儲,還會索引(index)每個文檔的内容使之可以被搜尋。在Elasticsearch中,你可以對文檔(而非成行成列的資料)進行索引、搜尋、排序、過濾。這種了解資料的方式與以往完全不同,這也是Elasticsearch能夠執行複雜的全文搜尋的原因之一。

二、Json ELasticsearch使用JSON,作為文檔序列化格式。 三、索引 還是以上面的商品為例,我有這樣一個需求 1、檢索任何商品的所有資訊。

2、支援結構化搜尋,例如查找價格為20元以上的商品。

3、支援簡單的全文搜尋和更複雜的短語搜尋

4、高亮搜尋結果中的關鍵字

5、能夠利用圖表管理分析這些資料

每個文檔代表一個商品,在考慮這些之前我們應該要知道資料要存在什麼地方 在Elasticsearch中,文檔歸屬于一種類型(type),而這些類型存在于索引(index:它是相關文檔存儲的地方)中,我們可以畫一些簡單的對比圖來類比傳統關系型資料庫:

Relational DB -> Databases -> Tables -> Rows -> Columns

Elasticsearch -> Indices   -> Types  -> Documents -> Fields

Elasticsearch叢集可以包含多個索引(indices)(資料庫),每一個索引可以包含多個類型(types)(表),每一個類型包含多個文檔(documents)(行),然後每個文檔包含多個字段(Fields)(列)

預設情況下,文檔中的所有字段都會被索引(擁有一個反向索引),隻有這樣他們才是可被搜尋的。

現在我建立一個文檔 每個文檔的類型為product

PUT /mytest/product/1
{
    "productName": "商品名稱",
    "productCode": "商品編号",
    "model": [
        {
            "name": "型号1"
        },
        {
            "name": "型号2"
        }
    ]
}
           
ElasticSearch基礎知識--檢索文檔

我們可以加多幾個文檔,友善到時候進行搜尋

PUT /mytest/product/2
{
    "productName": "商品名稱2",
    "productCode": "商品編号2",
    "model": [
        {
            "name": "型号4"
        },
        {
            "name": "型号5"
        }
    ]
}
           
PUT /mytest/product/3
{
    "productName": "商品名稱3",
    "productCode": "商品編号3",
    "model": [
        {
            "name": "型号6"
        },
        {
            "name": "型号7"
        }
    ]
}
           

四、檢索文檔 1、簡單搜尋

mytest/product/1
           
ElasticSearch基礎知識--檢索文檔

2、搜尋全部商品資訊

mytest/product/_search
           
ElasticSearch基礎知識--檢索文檔

我們在結尾使用關鍵字_search來取代原來的文檔ID。響應内容的hits數組中包含了我們所有的三個文檔。預設情況下搜尋會傳回前10個結果

3、query string:搜尋姓氏中包含“2”的商品  這種方法常被稱作查詢字元串(query string)搜尋,請求中依舊使用_search關鍵字然後加上"?q=",比如:/mytest/product/_search?q=productName:2

ElasticSearch基礎知識--檢索文檔

4、 使用DSL語句查詢:Elasticsearch提供豐富且靈活的查詢語言叫做DSL查詢(Query DSL),它允許你建構更加複雜、強大的查詢。

GET /mytest/product/_search
{
    "query" : {
        "match" : {
            "productName" : "2"
        }
    }}
           
ElasticSearch基礎知識--檢索文檔

5、全文搜尋

GET /mytest/product/_search
{
    "query" : {
    "match" : {
    "productName" : "商品3"
        }
    }}
           
ElasticSearch基礎知識--檢索文檔

預設情況下,Elasticsearch根據結果相關性評分來對結果集進行排序,所謂的「結果相關性評分」就是文檔與查詢條件的比對程度。很顯然,排名第一的‘商品名稱3‘’的productName字段明确的寫到“商品3”。

但是為什麼‘商品名稱2’和'商品名稱'也會出現在結果裡呢?原因是“商品”在她的productName字段中被提及了。因為隻有“商品”被提及而“3”沒有,是以她的_score要低于‘商品名稱3’。

這個例子很好的解釋了Elasticsearch如何在各種文本字段中進行全文搜尋,并且傳回相關性最大的結果集。相關性(relevance)的概念在Elasticsearch中非常重要,而這個概念在傳統關系型資料庫中是不可想象的,因為傳統資料庫對記錄的查詢隻有比對或者不比對。

6、短語搜尋

有時候我們想确切的比對若幹個單詞或者短語(phrases) ,那就使用match_phrase

GET /mytest/product/_search
{
    "query"       : {
    "match_phrase"       : {
    "productName" : "商品名稱3"
        }
    }}
           

上面的查詢将隻傳回‘商品名稱3’這個一個文檔

7、高亮搜尋(highlight)

GET /mytest/product/_search
{
    "query"       : {
    "match_phrase"       : {
    "productName" : "名稱3"
        }
      
    }
      ,
    "highlight": {
        "fields" : {
            "productName" : {}
        }
    }}
           
ElasticSearch基礎知識--檢索文檔

當我們運作這個語句時,會命中與之前相同的結果,但是在傳回結果中會有一個新的部分叫做highlight,這裡包含了來自about字段中的文本,并且用<em></em>來辨別比對到的單詞。

8、聚合

 Elasticsearch有一個功能叫做聚合(aggregations),它允許你在資料上生成複雜的分析統計。它很像SQL中的GROUP BY但是功能更強大。

首先在5.X後直接使用下面代碼進行聚合操作時提示“Fielddata is disabled on text fields by default。。。”的錯誤

GET /mytest/product/_search
 {
    "aggs" : {
        "all_productName" : {
            "terms" : { "field" : "productName" }
            
        }
    }
} 
           

具體解決方法在 這裡(原因:聚合這些操作用單獨的資料結構(fielddata)緩存到記憶體裡了,需要單獨開啟)。是以在5.X以後需要加上

PUT mytest/_mapping/product
{
  "properties": {
    "productName": { 
      "type":     "text",
      "fielddata": true
    }
  }
}
           
ElasticSearch基礎知識--檢索文檔

聚合也允許分級彙總比如,統計上述結果中商品的平均價格,那麼首先我先加入價格字段 "price" 那麼我查詢的所有資料就帶上了價格字段 類似這樣

{"took":0,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":3,"max_score":1.0,"hits":[{"_index":"mytest","_type":"product","_id":"2","_score":1.0,"_source":{
    "productName": "商品名稱2",
    "productCode": "商品編号2",
    "price": 200,
    "model": [
        {
            "name": "型号1"
        },
        {
            "name": "型号2"
        }
    ]
}
},{"_index":"mytest","_type":"product","_id":"1","_score":1.0,"_source":{
    "productName": "商品名稱1",
    "productCode": "商品編号1",
    "price": 100,
    "model": [
        {
            "name": "型号1"
        },
        {
            "name": "型号2"
        }
    ]
}
},{"_index":"mytest","_type":"product","_id":"3","_score":1.0,"_source":{
    "productName": "商品名稱3",
    "productCode": "商品編号3",
    "price": 300,
    "model": [
        {
            "name": "型号1"
        },
        {
            "name": "型号2"
        }
    ]
}
}]}}
           

查詢平均價格

GET /mytest/product/_search
 {
    "aggs" : {
        "all_productName" : {
            "terms" : { "field" : "productName" },
            "aggs" : {
                "avg_price" : {
                    "avg" : { "field" : "price" }
                }
            }
            
        }
    }
}
           
ElasticSearch基礎知識--檢索文檔

繼續閱讀