ElasticSearch代碼和知識點總結(一)
最近一直在學習怎麼用ElasticSearch這個搜索引擎,下面就是我的一些使用經驗,會結合代碼進行說明
場景說明:首先我現在的使用場景是利用python做後端,使用flask restful框架,查詢ElasticSearch的數據,返回Json數據
首先是安裝,要先安裝Java,因為els是基於Java的,具體可以參照這篇文章,
在Windows上安裝Elasticsearch5.x
,親測有效,裡面說明了怎麼安裝els和els-head,但現在好像都是Elasticsearch + Logstash + Kibana了,據我所知Logstash是用來解決讀寫分離的,也就是說讓資料庫mysql之類的資料庫進行刪除,更改,增加的操作,而Elasticsearch只進行查找,
關於這部分我還沒有搭建成功,也就是實現mysql數據和elasticsearch數據實時同步,據說有兩種常見方法:1.go-mysql-elasticsearch 2.logstash,關於這兩個方面我也會不斷的學習,爭取快點把它搭建出來
首先我覺得這篇博客的一些概念介紹的非常不錯,將els的index與mysql的表結構進行了比較,
使用 Elasticsearch 實現博客站內搜索
,同時這篇博主也提到了關於讀寫分離的問題,但是他並沒有明說具體是怎麼做的,比較遺憾
Python Elasticsearch Client接下來用Python Elasticsearch Client去做查詢,
Python + Elasticsearch. First steps. - Tryolabs Blog,這篇文章也非常不錯,教會你怎麼去用els去查詢星戰的角色,我就是看了這一篇文章明白了怎麼去做的
接下來就是寫flask restful介面了,相當於提供一個web服務,別人請求這個網址的時候,就可以返回查詢數據,其實也可以用django rest去寫,原理都差不多,如果為了省事用flask restful就可以,畢竟比較簡單
https://flask-restful.readthedocs.io/en/latest/quickstart.htmlQuickstart - Flask-RESTful 0.3.6 documentationQuickstart - Flask-RESTful 0.3.6 documentation
接下來貼上我的代碼
#! python3# -*- coding: utf-8 -*-from flask import Flask, jsonifyfrom flask_restful import reqparse, Api, Resourcefrom elasticsearch import Elasticsearches = Elasticsearch([{host: localhost, port: 9200}])app = Flask(__name__)api = Api(app)parser = reqparse.RequestParser()parser.add_argument(query, required=False)parser.add_argument(pageSize, type=int, default=10, required=False)parser.add_argument(currentPage, type=int, default=1, required=False)class Search(Resource): def get(self): """ 發送get請求去查詢els引擎並返回結果 :param query: 查詢欄位 :param size: 單頁結果數 :param offset: 從哪個結果開始 :return: """ args = parser.parse_args() query = args[query] # 查詢欄位 pageSize = args[pageSize] # 一頁有多少結果,默認是5 currentPage = args[currentPage] # 當前的頁數,搜索結果從哪裡開始,默認是0 if not query: return {list: [], pagination: {total: 0, pageSize: 5, current: 0}}, 200 search_res = es.search(index=frommysql, body={query: {multi_match: {query: query, fields: [title, content]}}, "highlight": {"fields": {"title": {}, content: {}}}}, size=pageSize, from_=currentPage) total_els_res_length = int(search_res[_shards][total]) # els搜索返回的結果有多少條 if total_els_res_length == 0: return {list: [], pagination: {total: 0, pageSize: 5, current: 0}}, 200 else: # 如果返回的是正常內容,要對els的數據重新組織一下結構 hit_res = search_res[hits][hits] search_list = [] for item in hit_res: _source = item[_source] object_id = _source[object_id] title = _source[title] content = _source[content] binary_sentiment = _source[binary_sentiment] source_name = _source[source] source_href = _source[url] updated_at = _source[occur_time] keywords = _source[keyword] tag_list = [] if keywords: keyword_list = keywords.split( ) for keyword_index, keyword_item in enumerate(keyword_list): tag_list_item = {id: tag-%s % keyword_index, name: keyword_item} tag_list.append(tag_list_item) search_dict = {id: object_id, negative: binary_sentiment, title: title, sourceName: source_name, sourceHref: source_href, content: content, updatedAt: updated_at, tagList: tag_list} search_list.append(search_dict) front_receive_data = {list: search_list, pagination: {total: total_els_res_length, pageSize: pageSize, current: currentPage}} return front_receive_data, 200class SearchHotNews(Resource): def get(self): """ 利用q普通查詢 搜索熱門新聞 :return: """ keywords = [{keyword: 區塊鏈}, {keyword: 概念股}, {keyword: 人工智慧}, {keyword: Google}, {keyword: 量子計算機}, {keyword: 無人車}, {keyword: 無人超市}, {keyword: SpaceX}, {keyword: 量子通信}, {keyword: 比特幣}] return jsonify(keywords)# api.add_resource(SearchList, /searchlist) # 返回結果列表api.add_resource(Search, /api/search/query)api.add_resource(SearchHotNews, /api/search/hot)if __name__ == __main__: app.run(host=0.0.0.0, port=9001, debug=True)# api.add_resource(SearchHotNews, /hot)# http://localhost:5000/hot?query=google&size=10&offset=0 # 啟動服務後, 在網址中發送get請求# 啟動0.0.0.0埠後,通過ipconfig查看ipv4地址,然後去訪問192.168.1.191:1080即可
這裡有幾個關鍵點需要說明一下
- 一個是flask restful是通過覆蓋不同的類下的get put post delete方法去映射介面,就相當於之前flask傳統模式下的路由@app.route 映射url,一樣的道理
- 然後就是這裡傳參數是同過reqparse這個模塊去傳參的,然後在類方法下接收參數,然後在瀏覽器里訪問的時候,要通過固定的格式去訪問地址,比方說我寫了 api.add_resource(SearchHotNews, /hot),那麼之前我又規定了三個參數query,pagesize,currentpage,那麼我訪問的時候,就應該訪問地址http://localhost:5000/hot?query=google&pagesize=10¤tpage=0
- 同時最後我想說明一點的是,els的查詢參數裡面可以傳入size, from_兩個參數來達到分頁目的,就是查詢結果是從第幾個開始的,一頁返回多少個結果
- 關於如何向els裡面插入數據,代碼很簡單,首先新建一個字典,代表你要插入的數據,res = {}, es.index(index=indexname, doc_type=xxx, id=xxx, body=res)即可
- 刪除els中的index,es.indices.delete(index=indexname, ignore=[400, 404])
那麼這一節的教程就結束了,接下來我會重點講解如何實現讀寫分離,反正繼續深入研究,因為這點東西肯定還不夠,還有現在我很感興趣的一個問題,如果有大神知道也可以告訴我一下啊,就是關於搜索引擎搜索關鍵詞自動補全是怎麼做的呢?
Algorithm for autocomplete?我在stackoverflow上看到這個解答,還沒有仔細研究代碼怎麼寫
推薦閱讀:
※《Neural Response Generation with Dynamic Vocabularies》閱讀筆記
※University Of Michigan: Learning Text Classifiers in Python
※University Of Michigan - Generative Models and LDA
※聊聊文本的分散式表示: Distributional Representation和Distributed Representation的區別
※Deep Learning 最優化方法之AdaGrad
TAG:Elasticsearch | 机器学习 | 自然语言处理 |