elasticsearch入門

標簽: search


elasticsearch 是一款非常強大的搜索開源搜索和分析軟件,高擴展高可用。

最新版本 1.7.2 搜索很強大,結合中文分詞,可以高效的檢索數據,給出符合查詢條件的數據,并排序賦予權重得分。

本篇只是入門級講解,大部分常用的功能基本涉及到了。

elasticsearch 是一款非常成熟的產品,如果需要更深層次的理解,需要詳細閱讀 官方文檔


目前狀況

雖然 elasticsearch 很強大,但是數據需要自己組織結構并導入。1.5 之前的版本支持 river 插件,可以通過插件直接從數據庫同步數據到 elasticsearch 中,但是目前版本已經 不推薦數據導入插件,所以需要自己寫 數據同步模塊

中文分詞 可以使用,該插件支持實時更新熱詞,并且可以配置不同的分詞策略。

elasticsearch 基于 java 開發,運行需要安裝 java 環境。接口為 Restful 風格,實際使用時可以按照 CURD 的原則使用相應的 Http 協議。

默認配置綁定 localhost ,端口 9200


數據結構

數據存儲結構為 /{index}/{type}/{id} ,使用三級結構保存數據,原始數據保存為 JSON

例如:

PUT /index/test/1
{ "title": "最新電影" }

GET /index/test/1
{
    "_index": "index",
    "_type": "test",
    "_id": "1",
    "_version": 1,
    "found": true,
    "_source": {
        "title": "最新電影"
    }
}

原始文檔存放在 _source 下,并且存儲的數據添加了其他 MetaData 信息 _index _type _id _version ,再次使用 PUT 可以更新文檔,使 _version 變為 2


數據導入

數據導入可以通過 Post 來完成。

1. 建立Index

建立一個普通的 _index ,不用傳任何參數 :

PUT http://localhost:9200/test
// 返回
{
    "acknowledged": true
}

如果需要使用 Analysis (語句分詞分析) ,則可以設置詳細的 _index

PUT http://localhost:9200/test
{
  "settings": {
     "refresh_interval": "5s",
     "number_of_shards" :   1, // 一個主節點,默認5
     "number_of_replicas" : 0 // 0個副本,后面可以加,默認1
  },
  "mappings": {
    "_default_":{
      "_all": { "enabled":  false } // 關閉_all字段,因為我們只搜索title字段
    },
    "resource": { // 這個是 _type
      "dynamic": false, // 關閉“動態修改索引”
      "properties": {
        "title": { // 表明對title字段進行分詞分析
          "type": "string",
          "index": "analyzed",
          "fields": { // elasticsearch可以識別語言
            "cn": { // 中文使用中文分詞
              "type": "string",
              "analyzer": "ik_smart"
            },
            "en": { // 英文使用英文分詞
              "type": "string",
              "analyzer": "english"
            }
          }
        }
      }
    }
  }
}

然后向上述 _index(test) 下導入數據:

POST /test/resource/ { "title": "周星馳" } // 這種會自動生成id
PUT /test/resource/1?op_type=create { "title": "周星馳" }
PUT /test/resource/1/_create { "title": "周星馳" }

上述的第一種方式會自動生成 _id

POST /_bulk or /test/_bulk or /test/resource/_bulk
{ "create": { "_index": "test", "_type": "resource", "_id": 1 } }
{ "title": "周星馳最新電影" }
{ "create": { "_index": "test", "_type": "resource", "_id": 2 } }
{ "title": "周星馳最好看的新電影" }
{ "create": { "_index": "test", "_type": "resource", "_id": 3 } }
{ "title": "周星馳最新電影,最好,新電影" }
{ "create": { "_index": "test", "_type": "resource", "_id": 4 } }
{ "title": "最最最最好的新新新新電影" }
{ "create": { "_index": "test", "_type": "resource", "_id": 5 } }
{ "title": "I'm not happy about the foxes" }

也可以將 /_bulk 提交的內容放入一個文本(文件末尾必須有一空行 \n

curl -s -XPOST localhost:9200/_bulk --data-binary "@requests"
// 已經存在會報錯
{
  "error" : "DocumentAlreadyExistsException[[website][4] [blog][123]:
             document already exists]",
  "status" : 409
}

數據檢索

Retrieving 檢索文檔

可以使用 Head 判斷是否存在

HEAD /{index}/{type}/{id}

可以直接檢索到 id 一級,精確獲取文檔。

// pretty會格式化JSON
GET /{index}/{type}/{id}[?pretty][&_source=field1,field...]

_source命令可以精確檢索字段

可以使用 _search 命令:

GET /{index}/_search or /{index}/{type}/_search
// 返回示例
{
    "took": 1, // 耗費毫秒數 
    "timed_out": false, // 可以在命令中設置?timeout=10ms
    "_shards": { // 分區
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": { // 所有文檔
        "total": 2,
        "max_score": 1,
        "hits": [ // 所有文檔
          {
            "_index": "test",
            "_type": "resource",
            "_id": 1,
            "_score": 1,
            "_source": {
              "title": "周星馳"
            }
          },
          ...
        ]
    }
}

如果開啟了 Analysis ,使用 multi_match 則可以按關鍵字(分詞)進行搜索,返回結果按 _score 來排序。

POST /{index}/{type}/_search
{
  "query": {
    "multi_match": {
      "type":     "most_fields", 
      "query":    "周星馳最新電影fox",
      "fields": ["title", "title.cn", "title.en"]
    }
  }
}
// 返回示例
{
    "took": 7,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "failed": 0
    },
    "hits": {
        "total": 5,
        "max_score": 1.4102149,
        "hits": [
            {
                "_index": "index",
                "_type": "test",
                "_id": "1",
                "_score": 1.4102149,
                "_source": {
                    "title": "周星馳最新電影"
                }
            },
            {
                "_index": "index",
                "_type": "test",
                "_id": "3",
                "_score": 1.1354887,
                "_source": {
                    "title": "周星馳最新電影,最好,新電影"
                }
            },
            {
                "_index": "index",
                "_type": "test",
                "_id": "2",
                "_score": 1.0024924,
                "_source": {
                    "title": "周星馳最好看的新電影"
                }
            },
            {
                "_index": "index",
                "_type": "test",
                "_id": "4",
                "_score": 0.31740457,
                "_source": {
                    "title": "最最最最好的新新新新電影"
                }
            },
            {
                "_index": "index",
                "_type": "test",
                "_id": "5",
                "_score": 0.013072087,
                "_source": {
                    "title": "I'm not happy about the foxes"
                }
            }
        ]
    }
}

還可以加上 分頁高亮以及最小匹配度

POST /{index}/{type}/_search
{
  "query": {
    "multi_match": {
      "type":     "most_fields",  // 搜索使用的模式
      "query":    "周星馳最新電影fox",
      "fields": [ "title", "title.cn", "title.en" ], // 設置搜索的范圍
      "minimum_should_match": "20%" // 最小匹配度
    }
  },
  "from": 0,
  "size": 10,
  "highlight" : {
    "pre_tags" : ["<strong>"],
    "post_tags" : ["</strong>"],
    "fields" : {
      "title" : {},
      "title.cn" : {},
      "title.en" : {}
    }
  }
}
// 返回
{
    "took": 13,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "failed": 0
    },
    "hits": {
        "total": 5,
        "max_score": 1.1782398,
        "hits": [
            {
                "_index": "test",
                "_type": "resource",
                "_id": "1",
                "_score": 1.1782398,
                "_source": {
                    "title": "周星馳最新電影"
                },
                "highlight": {
                    "title": [
                        "<strong>周</strong><strong>星</strong><strong>馳</strong><strong>最</strong><strong>新</strong><strong>電</strong><strong>影</strong>"
                    ],
                    "title.cn": [
                        "<strong>周星馳</strong><strong>最新</strong><strong>電影</strong>"
                    ],
                    "title.en": [
                        "<strong>周</strong><strong>星</strong><strong>馳</strong><strong>最</strong><strong>新</strong><strong>電</strong><strong>影</strong>"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "resource",
                "_id": "3",
                "_score": 0.9440402,
                "_source": {
                    "title": "周星馳最新電影,最好,新電影"
                },
                "highlight": {
                    "title": [
                        "<strong>周</strong><strong>星</strong><strong>馳</strong><strong>最</strong><strong>新</strong><strong>電</strong><strong>影</strong>,<strong>最</strong>好,<strong>新</strong><strong>電</strong><strong>影</strong>"
                    ],
                    "title.cn": [
                        "<strong>周星馳</strong><strong>最新</strong><strong>電影</strong>,最好,<strong>新</strong><strong>電影</strong>"
                    ],
                    "title.en": [
                        "<strong>周</strong><strong>星</strong><strong>馳</strong><strong>最</strong><strong>新</strong><strong>電</strong><strong>影</strong>,<strong>最</strong>好,<strong>新</strong><strong>電</strong><strong>影</strong>"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "resource",
                "_id": "2",
                "_score": 0.8302629,
                "_source": {
                    "title": "周星馳最好看的新電影"
                },
                "highlight": {
                    "title": [
                        "<strong>周</strong><strong>星</strong><strong>馳</strong><strong>最</strong>好看的<strong>新</strong><strong>電</strong><strong>影</strong>"
                    ],
                    "title.cn": [
                        "<strong>周星馳</strong><strong>最</strong>好看的<strong>新</strong><strong>電影</strong>"
                    ],
                    "title.en": [
                        "<strong>周</strong><strong>星</strong><strong>馳</strong><strong>最</strong>好看的<strong>新</strong><strong>電</strong><strong>影</strong>"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "resource",
                "_id": "4",
                "_score": 0.255055,
                "_source": {
                    "title": "最最最最好的新新新新電影"
                },
                "highlight": {
                    "title": [
                        "<strong>最</strong><strong>最</strong><strong>最</strong><strong>最</strong>好的<strong>新</strong><strong>新</strong><strong>新</strong><strong>新</strong><strong>電</strong><strong>影</strong>"
                    ],
                    "title.cn": [
                        "最最<strong>最</strong>最好的新新新新<strong>電影</strong>"
                    ],
                    "title.en": [
                        "<strong>最</strong><strong>最</strong><strong>最</strong><strong>最</strong>好的<strong>新</strong><strong>新</strong><strong>新</strong><strong>新</strong><strong>電</strong><strong>影</strong>"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "resource",
                "_id": "5",
                "_score": 0.012243208,
                "_source": {
                    "title": "I'm not happy about the foxes"
                },
                "highlight": {
                    "title.en": [
                        "I'm not happy about the <strong>foxes</strong>"
                    ]
                }
            }
        ]
    }
}

elasticsearch 雖然可以識別語言類型,但是可以看到,英文分詞對中文是每個字都區分開了,中文分詞則不支持英文。所以使用的時候需要注意。

在上述例子中, multi_match 使用了 most_fields,表示匹配任何滿足條件的 fieldmulti_match支持如下幾種模式:

  • best_fields
    默認模式,搜索任何 field ,但是使用 _score 是所有 field 中最高的一項。

  • most_fields
    搜索任何 field ,但是 _score 是所有 field 的和值。

  • cross_fields
    將所有 field 看成是一個進行搜索。

  • match_phrase or match_phrase_prefix
    兩個與 best_fields 類似,但是會把 fileds 拆開,變成多個 queries

{
  "multi_match" : {
    "query":      "quick brown f",
    "type":       "phrase_prefix",
    "fields":     [ "subject", "message" ]
  }
}
// to
{
  "dis_max": {
    "queries": [
      { "match_phrase_prefix": { "subject": "quick brown f" }},
      { "match_phrase_prefix": { "message": "quick brown f" }}
    ]
  }
}

刪除文檔

DELETE 用來刪除文檔。

不會立即刪除,只是標記刪除,在需要的時候再刪除。

DELETE /{index}  刪除整個index
DELETE /{index}/{type} 刪除type一級
DELETE /{index}/{type}/{id} 刪除具體的某個文檔
// 200
{
  "found" :    true,
  "_index" :   "x",
  "_type" :    "x",
  "_id" :      "x",
  "_version" : 3
}
// 404
{
  "found" :    false,
  "_index" :   "x",
  "_type" :    "x",
  "_id" :      "x",
  "_version" : 4
}

中文分詞

https://github.com/medcl/elasticsearch-analysis-ik

配置,使用配置1或者2

elasticsearch.yml
// 1
index:
  analysis:
    analyzer:
      ik:
          alias: [ik_analyzer]
          type: org.elasticsearch.index.analysis.IkAnalyzerProvider
      ik_max_word:
          type: ik
          use_smart: false
      ik_smart:
          type: ik
          use_smart: true
// 2
index.analysis.analyzer.ik.type : "ik" // = ik_max_word

ik_max_word 會將文本做最細粒度的拆分,如

『中華人民共和國國歌』被拆分成
『中華人民共和國』
『中華人民』
...
『國歌』,會窮盡各種可能的組合

ik_smart 會做最粗粒度的拆分,如

『中華人民共和國國歌』拆分為
『中華人民共和國』
『國歌』

在之前的例子中已經使用到了這個分詞插件。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容