天天看點

全文檢索(elasticsearch入門)

Elasticsearch篇:

Elasticsearch是一個采用java語言開發的,基于Lucene構造的開源,分布式的搜尋引擎. 設計用于雲計算中,能夠達到實時搜尋,穩定可靠. Elasticsearch的資料模型是JSON. 對于需要分布式需求的這是一個非常好的選擇,部署簡單,同網段内會自動組成叢集服務無需配置。其內建資料庫同步插件,不僅支援幾乎實時的全文檢索服務,還支援距離查詢,提供類似類似百度地圖離我最近查詢。

官方首頁:http://www.elasticsearch.org/ 

中文詞庫支援ik:https://github.com/medcl/elasticsearch-analysis-ik

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

mysql實時自動資料到Elasticsearch 插件:https://github.com/jprante/elasticsearch-river-jdbc

中文支援版下載下傳:經過作者吐血內建了ik中文分詞器與mysql插件elasticsearch-river-jdbc,

下載下傳位址:http://songwie.com/attached/lucene/elasticsearch-rtf.zip

 spring 對java api 的內建:https://github.com/spring-projects/spring-data-elasticsearch

目前有好多的提供全文檢索引擎服務的項目,選擇了一個分布式的可以支援叢集模式的使用,Elasticsearch無需部署即可使用,rtf內建版內建了ik中文詞庫,jdbc-rever等插件。

基礎概念

    Elasticsearch有幾個核心概念。從一開始了解這些概念會對整個學習過程有莫大的幫助。

接近實時(NRT)

        Elasticsearch是一個接近實時的搜尋平台。這意味着,從索引一個文檔直到這個文檔能夠被搜尋到有一個輕微的延遲(通常是1秒)。    

叢集(cluster)

        一個叢集就是由一個或多個節點組織在一起,它們共同持有你整個的資料,并一起提供索引和搜尋功能。一個叢集由一個唯一的名字辨別,這個名字預設就是 “elasticsearch”。這個名字是重要的,因為一個節點隻能通過指定某個叢集的名字,來加入這個叢集。在 産品環境中顯式地設定這個名字是一個好 習慣,但是使用預設值來進行測試/開發也是不錯的。     

節點(node)

        一個節點是你叢集中的一個伺服器,作為叢集的一部分,它存儲你的資料,參與叢集的索引和搜尋功能。和叢集類似,一個節點也是由一個名字來辨別的,預設情況 下,這個名字是一個随機的漫威漫畫角色的名字,這個名字會在啟動的時候賦予節點。這個名字 對于管理工作來說挺重要的,因為在這個管理過程中,你會去确定網 絡中的哪些伺服器對應于Elasticsearch叢集中的哪些節點。     

        一個節點可以通過配置叢集名稱的方式來加入一個指定的叢集。預設情況下,每個節點都會被安排加入到一個叫做“elasticsearch”的叢集中,這意味着,如果你在你的網絡中啟動了若幹個節點,并假定它們能夠互相發現彼此,它們将會自動地形成并加入到一個叫做“elasticsearch”的叢集中。    

        在一個叢集裡,隻要你想,可以擁有任意多個節點。而且,如果目前你的網絡中沒有運作任何Elasticsearch節點,這時啟動一個節點,會預設建立并加入一個叫做“elasticsearch”的叢集。    

索引(index)    

        一個索引就是一個擁有幾分相似特征的文檔的集合。比如說,你可以有一個客戶資料的索引,另一個産品目錄的索引,還有一個訂單資料的索引。一個索引由一個名 字來辨別(必須全部是小寫字母的),并且當我們要對對應于這個索引中的文檔進行索引、搜尋、更新和删除的時候,都要使用到這個名字。   

       在一個叢集中,如果你想,可以定義任意多的索引。      

類型(type)

        在一個索引中,你可以定義一種或多種類型。一個類型是你的索引的一個邏輯上的分類/分區,其語義完全由你來定。通常,會為具有一組共同字段的文檔定義一個 類型。比如說,我們假設你營運一個部落格平台并且将你所有的資料存儲到一個索引中。在這個索引中,你可以為使用者資料定義一個類型,為部落格資料定義另一個類 型,當然,也可以為評論資料定義另一個類型。  

文檔(document)      

        一個文檔是一個可被索引的基礎資訊單元。比如,你可以擁有某一個客戶的文檔,某一個産品的一個文檔,當然,也可以擁有某個訂單的一個文檔。文檔以 JSON(Javascript Object Notation)格式來表示,而JSON是一個到處存在的網際網路資料互動格式。       

        在一個index/type裡面,隻要你想,你可以存儲任意多的文檔。注意,盡管一個文檔,實體上存在于一個索引之中,文檔必須被索引/賦予一個索引的type。        

分片和複制(shards & replicas)        

        一個索引可以存儲超出單個結點硬體限制的大量資料。比如,一個具有10億文檔的索引占據1TB的磁盤空間,而任一節點都沒有這樣大的磁盤空間;或者單個節點處理搜尋請求,響應太慢。        

        為了解決這個問題,Elasticsearch提供了将索引劃分成多份的能力,這些份就叫做分片。當你建立一個索引的時候,你可以指定你想要的分片的數量。每個分片本身也是一個功能完善并且獨立的“索引”,這個“索引”可以被放置到叢集中的任何節點上。        

        分片之是以重要,主要有兩方面的原因:        

            - 允許你水準分割/擴充你的内容容量

            - 允許你在分片(潛在地,位于多個節點上)之上進行分布式的、并行的操作,進而提高性能/吞吐量        

        至于一個分片怎樣分布,它的文檔怎樣聚合回搜尋請求,是完全由Elasticsearch管理的,對于作為使用者的你來說,這些都是透明的        

        在一個網絡/雲的環境裡,失敗随時都可能發生,在某個分片/節點不知怎麼的就處于離線狀态,或者由于任何原因消失了,這種情況下,有一個故障轉移機制是非 常有用并且是強烈推薦的。為此目的,Elasticsearch允許你建立分片的一份或多份拷貝,這些拷貝叫做複制分片,或者直接叫複制。        

        複制之是以重要,有兩個主要原因:

            - 在分片/節點失敗的情況下,提供了高可用性。因為這個原因,注意到複制分片從不與原/主要(original/primary)分片置于同一節點上是非常重要的。

            - 擴充你的搜尋量/吞吐量,因為搜尋可以在所有的複制上并行運作            

        總之,每個索引可以被分成多個分片。一個索引也可以被複制0次(意思是沒有複制)或多次。一旦複制了,每個索引就有了主分片(作為複制源的原來的分片)和 複制分片(主分片的拷貝)之别。分片和複制的數量可以在索引建立的時候指定。在索引建立之後,你可以在任何時候動态地改變複制的數量,但是你事後不能改變 分片的數量。        

        預設情況下,Elasticsearch中的每個索引被分片5個主分片和1個複制,這意味着,如果你的叢集中至少有兩個節點,你的索引将會有5個主分片和另外5個複制分片(1個完全拷貝),這樣的話每個索引總共就有10個分片。        

        這些問題搞清楚之後,我們就要進入好玩的部分了...

curl -<REST Verb> <Node>:<Port>/<Index>/<Type><ID>

部署:

Elasticsearch是一個綠色版無需安裝即可使用:

Elasticsearch需要的jdk版本為1.7:

windows下安裝

        一:到官網 http://www.elasticsearch.org/download 或者下載下傳中文內建的版本:https://github.com/medcl/elasticsearch-rtf 

        二:配置系統環境變量:JAVA_HOME: 實際jdk目錄,需要1.7及以上版本。

linux下安裝

        預設官方版與windows配置相同。

        中文內建版中:啟動插件環境變量配置:

                                bin\service\elasticsearch.conf   配置ES_HOME: set.default.ES_HOME=E:\service\elasticsearch-rtf  

啟動、停止服務

        預設官方版啟動:

                                   linux:./bin/elasticsearch start

                                   window:直接運作bin/elasticsearch.bat

         預設官方版停止:

                                   linux:kill 掉elasticsearch 程序。

                                   window:管理啟動的elasticsearch.bat 視窗

         中文內建版啟動與停止:

                                   中文內建版內建了 elasticsearch-servicewrapper這個es插件

                                   linux:

./elasticsearch console  ------前台運作
                         ./elasticsearch start    ------背景運作
                         ./elasticsearch install  -------添加到系統自動啟動
                         ./elasticsearch remove   -----取消随系統自動啟動      
./elasticsearch stop     ------停止      
./elasticsearch restart  ------重新啟動      

                                   window:直接運作elasticsearch.bat

記憶體配置情況

      JVM參數與Elasticsearch對照關系

JVM參數   Elasticsearch預設值 Environment變量
‘-Xms 256m ES_MIN_MEM
’-Xmx 1g ES_MAX_MEM
-Xms and -Xmx ES_HEAP_SIZE 
-Xmn  ES_HEAP_NEWSIZE
-XX:MaxDirectMemorySize  ES_DIRECT_SIZE

       官方版配置:

                         linux    配置:elasticsearch.bat 添加 set  Elasticsearch變量=值

                         window配置:elasticsearch.in.sh 添加 set  Elasticsearch變量=值

       中文內建版配置:

                        在service目錄下有個elasticsearch.conf配置檔案,主要是設定一些java運作環境參數,其中比較重要的是下面的參數:

                        set.default.ES_MIN_MEM=256

                        set.default.ES_MAX_MEM=1024

群集配置

常用叢集配置參數:config/elasticsearch.yml      
discovery.zen.ping.multicast.enabled: false   設定是否打開多點傳播發現節點,預設是true,如果為false 又沒有配置叢集清單則代表單機運作。      
discovery.zen.ping.unicast.hosts: ["host1", "host2:port", "host3[portX-portY]"]  設定叢集中master節點的初始清單,可以通過這些節點來自動發現新加入叢集的節點。      

配置檔案介紹

 elasticsearch的config檔案夾裡面有兩個配置檔案:elasticsearch.yml和logging.yml,第一個是es的基本配置檔案,第二個是日志配置檔案,es也是使用log4j來記錄日志的,是以logging.yml裡的設定按普通log4j配置檔案來設定就行了。

下面主要講解下elasticsearch.yml這個檔案中可配置的東西。

cluster.name: elasticsearch
配置es的叢集名稱,預設是elasticsearch,es會自動發現在同一網段下的es,如果在同一網段下有多個叢集,就可以用這個屬性來區分不同的叢集。
node.name: "Franz Kafka"
節點名,預設随機指定一個name清單中名字,該清單在es的jar包中config檔案夾裡name.txt檔案中,其中有很多作者添加的有趣名字。
node.master: true
指定該節點是否有資格被選舉成為node,預設是true,es是預設叢集中的第一台機器為master,如果這台機挂了就會重新選舉master。
node.data: true
指定該節點是否存儲索引資料,預設為true。
index.number_of_shards: 5
設定預設索引分片個數,預設為5片。
 
index.number_of_replicas: 1
設定預設索引副本個數,預設為1個副本。
path.conf: /path/to/conf
設定配置檔案的存儲路徑,預設是es根目錄下的config檔案夾。
path.data: /path/to/data
設定索引資料的存儲路徑,預設是es根目錄下的data檔案夾,可以設定多個存儲路徑,用逗号隔開,例:
path.data: /path/to/data1,/path/to/data2
path.work: /path/to/work
設定臨時檔案的存儲路徑,預設是es根目錄下的work檔案夾。
path.logs: /path/to/logs
設定日志檔案的存儲路徑,預設是es根目錄下的logs檔案夾
path.plugins: /path/to/plugins
設定插件的存放路徑,預設是es根目錄下的plugins檔案夾
bootstrap.mlockall: true
設定為true來鎖住記憶體。因為當jvm開始swapping時es的效率會降低,是以要保證它不swap,可以把ES_MIN_MEM和ES_MAX_MEM兩個環境變量設定成同一個值,并且保證機器有足夠的記憶體配置設定給es。
同時也要允許elasticsearch的程序可以鎖住記憶體,linux下可以通過`ulimit -l unlimited`指令。
network.bind_host: 192.168.0.1
設定綁定的ip位址,可以是ipv4或ipv6的,預設為0.0.0.0。
network.publish_host: 192.168.0.1
設定其它節點和該節點互動的ip位址,如果不設定它會自動判斷,值必須是個真實的ip位址。
network.host: 192.168.0.1
這個參數是用來同時設定bind_host和publish_host上面兩個參數。
transport.tcp.port: 9300
設定節點間互動的tcp端口,預設是9300。
transport.tcp.compress: true
設定是否壓縮tcp傳輸時的資料,預設為false,不壓縮。
http.port: 9200
設定對外服務的http端口,預設為9200。
http.max_content_length: 100mb
設定内容的最大容量,預設100mb
http.enabled: false
是否使用http協定對外提供服務,預設為true,開啟。
gateway.type: local
gateway的類型,預設為local即為本地檔案系統,可以設定為本地檔案系統,分布式檔案系統,hadoop的HDFS,和amazon的s3伺服器,其它檔案系統的設定方法下次再詳細說。
gateway.recover_after_nodes: 1
設定叢集中N個節點啟動時進行資料恢複,預設為1。
gateway.recover_after_time: 5m
設定初始化資料恢複程序的逾時時間,預設是5分鐘。
gateway.expected_nodes: 2
設定這個叢集中節點的數量,預設為2,一旦這N個節點啟動,就會立即進行資料恢複。
cluster.routing.allocation.node_initial_primaries_recoveries: 4
初始化資料恢複時,并發恢複線程的個數,預設為4。
cluster.routing.allocation.node_concurrent_recoveries: 2
添加删除節點或負載均衡時并發恢複線程的個數,預設為4。
indices.recovery.max_size_per_sec: 0
設定資料恢複時限制的帶寬,如入100mb,預設為0,即無限制。
indices.recovery.concurrent_streams: 5
設定這個參數來限制從其它分片恢複資料時最大同時打開并發流的個數,預設為5。
discovery.zen.minimum_master_nodes: 1
設定這個參數來保證叢集中的節點可以知道其它N個有master資格的節點。預設為1,對于大的叢集來說,可以設定大一點的值(2-4)
discovery.zen.ping.timeout: 3s
設定叢集中自動發現其它節點時ping連接配接逾時時間,預設為3秒,對于比較差的網絡環境可以高點的值來防止自動發現時出錯。
discovery.zen.ping.multicast.enabled: false
設定是否打開多點傳播發現節點,預設是true。
discovery.zen.ping.unicast.hosts: ["host1", "host2:port", "host3[portX-portY]"]
設定叢集中master節點的初始清單,可以通過這些節點來自動發現新加入叢集的節點。
下面是一些查詢時的慢日志參數設定
index.search.slowlog.level: TRACE
index.search.slowlog.threshold.query.warn: 10s
index.search.slowlog.threshold.query.info: 5s
index.search.slowlog.threshold.query.debug: 2s
index.search.slowlog.threshold.query.trace: 500ms
 
index.search.slowlog.threshold.fetch.warn: 1s
index.search.slowlog.threshold.fetch.info: 800ms
index.search.slowlog.threshold.fetch.debug:500ms
index.search.slowlog.threshold.fetch.trace: 200ms      

   正常啟動為:

 對于中文插件的內建與啟動插件的內建參考: http://www.51document.com/1364910818272.html

 rtf版本的啟動後會有一個界面:

 簡單入門使用:

中文詞庫 使用參考:https://github.com/medcl/elasticsearch-analysis-mmseg

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

參數說明:curl -<REST Verb> <Node>:<Port>/<Index>/<Type><ID>

//建立一個名為index的索引庫
curl -XPUT http://localhost:9200/index
 
//添加索引:
curl -XPOST http://localhost:9200/index/fulltext/1 -d'
{"content":"美國留給伊拉克的是個爛攤子嗎"}
'
curl -XPOST http://localhost:9200/index/fulltext/2 -d'
{"content":"公安部:各地校車将享最高路權"}
'
 
curl -XPOST http://localhost:9200/index/fulltext/3 -d'
{"content":"中韓漁警沖突調查:韓警平均每天扣1艘中國漁船"}
'
curl -XPOST http://localhost:9200/index/fulltext/4 -d'
{"content":"中國駐洛杉矶領事館遭亞裔男子槍擊 嫌犯已自首"}
'
curl -XPOST http://localhost:9200/index/fulltext/5 -d'
{"content":"美國留給伊拉克的是個爛攤子嗎","address":"陸家嘴78号"}
'
 
curl -XPOST http://localhost:9200/index/fulltext/6 -d'
{"content":"公安部:各地校車将享最高路權","address":"長吉路78号"}
'
curl -XPOST http://localhost:9200/index/fulltext/7 -d'
{"content":"中韓漁警沖突調查:韓警平均每天扣1艘中國漁船","address":"陸家嘴牡丹路78号"}
'
curl -XPOST http://localhost:9200/index/fulltext/8 -d'
{"content":"中國駐洛杉矶領事館遭亞裔男子槍擊 嫌犯已自首","address":"山東路78号"}
'
查詢:所有字段中包含嫌犯 山東路 的資料
 
curl -XPOST http://localhost:9200/index/fulltext/_search  -d'
{
"query" : { "match" : { "_all" : "嫌犯 山東路" }},
"highlight" : {
"pre_tags" : ["<hr>", "<hr>"],
"post_tags" : ["</hr>", "</hr>"],
"fields" : {
"content" : {}
}
},
'size': 10,
"sort": [
{
"content":"asc"
}
],
"highlight": {
"pre_tags": [
"<hr>",
"<hr>"
],
"post_tags": [
"</hr>",
"</hr>"
],
"fields": {
"content": {}
}
}
}
'
curl -XPOST http://localhost:9200/index/fulltext/_search  -d'
{
"query" : { "multi_match" : { "query" : "嫌犯 山東路","fields":     [ "content", "address" ] }},
"highlight" : {
"pre_tags" : ["<hr>", "<hr>"],
"post_tags" : ["</hr>", "</hr>"],
"fields" : {
"content" : {}
}
}
}
'
 
curl -XPOST http://localhost:9200/index/fulltext/_search  -d'
{
"query" : { "multi_match" : { "query" : "嫌犯 山東路","fields":     [ "content", "address" ], "operator":   "or" ,"minimum_should_match": "50%"}},
"highlight" : {
"pre_tags" : ["<hr>", "<hr>"],
"post_tags" : ["</hr>", "</hr>"],
"fields" : {
"content" : {}
}
}
}
'
 
curl -XPOST http://localhost:9200/index/fulltext/_search  -d'
{
"query" : { "more_like_this" : { "like_text" : "嫌犯","fields":     [ "content", "address" ] }},
"highlight" : {
"pre_tags" : ["<hr>", "<hr>"],
"post_tags" : ["</hr>", "</hr>"],
"fields" : {
"content" : {}
}
}
}
'
 
curl -XPOST http://localhost:9200/index/fulltext/_search  -d'
{
"query" : { "bool" : { "like_text" : "嫌犯","fields":     [ "content", "address" ] }},
"highlight" : {
"pre_tags" : ["<hr>", "<hr>"],
"post_tags" : ["</hr>", "</hr>"],
"fields" : {
"content" : {}
}
}
}
'
 
curl -XPOST http://localhost:9200/index/fulltext/_search  -d'
{
"query": {
"multi_match": {
"query": "嫌犯 陸家嘴 山東路",
"fields": [
"content",
"address"
],
"operator": "or",
"minimum_should_match": "50%"
}
},
"highlight": {
"pre_tags": [
"<hr>",
"<hr>"
],
"post_tags": [
"</hr>",
"</hr>"
],
"fields": {
"content": {}
}
}
}
'
 
 
 
 
curl -XPOST http://localhost:9200/index/fulltext/_search  -d'
{
"query": {
"bool": {
"should": [
{
"term": {
"_all": "嫌犯"
}
}
]
}
},
"sort": [
{
"address":"asc"
}
],
"highlight": {
"pre_tags": [
"<hr>",
"<hr>"
],
"post_tags": [
"</hr>",
"</hr>"
],
"fields": {
"content": {}
}
}
}
'       

含有距離搜尋使用geo_point:

參考資料:https://github.com/jprante/elasticsearch-river-jdbc/tree/1.0      
curl -XDELETE http://localhost:9200/venue
 
curl -XPOST http://localhost:9200/venue -d '
{
"mappings": {
"venue": {
"properties": {
"name": {
"type": "string"
},
"locations": {
"type": "geo_point"
}
}
}
}
}
'
 
 
curl -X POST "http://localhost:9200/venue/venue/" -d'
{"type":"venue","name":"One","locations":[40.1,-70.1]}'
 
 
 
curl -X POST "http://localhost:9200/venue/_refresh"
 
curl -POST 'http://localhost:9200/venue/_search?pretty' -d '
{
"query": {
"filtered": {
"query": {
"match" : { "_all" : "One" }
},
"filter": {
"geo_distance": {
"distance": "60000km",
"locations": {
"lat": 5.0,
"lon": 5.0
}
}
}
}
}
}
'
 
 
例子2:
 
 
curl -XDELETE 'http://localhost:9200/venue/'
curl -XPUT 'http://localhost:9200/venue/'
 
curl -XPUT 'http://localhost:9200/venue/tweet/_mapping' -d '
{
"tweet" : {
"properties" : {
"locations" : {"type" : "geo_point"}
}
}
}'
 
curl -XPUT 'http://localhost:9200/venue/tweet/1' -d '
{
"user": "kimchy",
"postDate": "2009-11-15T13:12:00",
"message": "Trying out Elastic Search, so far so good?",
"locations" : [
{
"lat" : 40.00,
"lon" : 9.00
}]
}'
 
curl -XPUT 'http://localhost:9200/venue/tweet/2' -d '
{
"user": "kimchy",
"postDate": "2009-11-15T13:12:00",
"message": "Trying out Elastic Search, so far so good?",
"locations" : [{
"lat" : 30.00,
"lon" : 8.00
}]
}'
 
curl -XGET 'http://localhost:9200/venue/tweet/_search' -d '{
"query": {
"filtered" : {
"query" : {
"match_all" : {}
},
"filter" : {
"geo_distance" : {
"distance" : "20km",
"locations" : {
"lat" : 40.00,
"lon" : 9.00
}
}
}
}
}
}'       

從mysql資料庫同步資料到elasticsearch使用:

插件使用介紹:https://github.com/jprante/elasticsearch-river-jdbc'         

                     https://github.com/jprante/elasticsearch-river-jdbc/tree/1.0

插件需要注意的是jdbc river插件已經對原始的配置做了結構修改,建立index必須按照其api來建立,

其中index 對應原來的index名字,type是建立的type名字,index_settings 裡面是elasticsearch原始配置setting api,

Type_mapping是elasticsearch原始配置mapping api,如果需要将資料庫row 記錄id當作索引主鍵則需要設定 别名,

例如:select vid as _id ,* from test 

其他字段類似,如下:

_index     the index this object should be indexed into
_type      the type this object should be indexed into
_id        the id of this object
_version   the version of this object
_parent    the parent of this object
_ttl       the time-to-live of this object
_routing   the routing of this object      
curl -XDELETE 'localhost:9200/_river/merchant/_meta'
 
curl -XPOST 'localhost:9200/_river/merchant/_meta' -d '
{
flush_interval: "3s",
type: "jdbc",
jdbc: {
url: "jdbc:mysql://xxx:3307/xrdb",
user: "root",
password: "root",
sql: "select * from 資料庫表",
locale: "zh_CN",
index: "laolaibao",
type: "merchant",
index_settings: {
index: {
number_of_shards: "2"
}
},
type_mapping: {
merchant: {
dynamic: true,
properties: {
MERCHANT_NAME: {
type: "string",
analyzer: "ik",
indexAnalyzer: "ik",
searchAnalyzer: "ik"
},
STREET_ADDRESS: {
type: "string",
analyzer: "ik",
indexAnalyzer: "ik",
searchAnalyzer: "ik"
},
LOCATIONS: {
type: "geo_point"
}
}
}
}
}
}
'
 
 
curl -XPOST http://localhost:9200/laolaibao/merchant/_search  -d'
{
"query" : { "match" : { "_all" : "寶得 吳淞路258号101室" }},
'size': 5 ,
"sort": [
{
"address":"asc"
}
],
"highlight": {
"pre_tags": [
"<hr>",
"<hr>"
],
"post_tags": [
"</hr>",
"</hr>"
],
"fields": {
"content": {}
}
}
}
'
 
curl -XPOST http://localhost:9200/laolaibao/merchant/_search  -d'
{
"query" : { "multi_match" : { "query" : "寶得萊 吳淞路","fields":     [ "MERCHANT_NAME", "STREET_ADDRESS" ] , "operator":   "or" ,"minimum_should_match": "70%"}},
'size': 2,
"sort": [
{
"address":"asc"
}
],
"highlight": {
"pre_tags": [
"<hr>",
"<hr>"
],
"post_tags": [
"</hr>",
"</hr>"
],
"fields": {
"content": {}
}
}
}
'
 
curl -XPOST 'http://localhost:9200/laolaibao/merchant/_search?pretty' -d '
{
query: {
filtered: {
query: {
match_all: { }
},
filter: {
geo_distance: {
distance: "50000km",
LOCATIONS: {
lat: "37.752258",
lon: "-121.949886"
}
}
}
}
}
}
'      
  1. Java api 使用:

  2. 官方參考:http://www.elasticsearch.org/guide/en/elasticsearch/client/java-api spring 對java api 的內建:https://github.com/spring-projects/spring-data-elasticsearch

Pom引入:
           
<dependency>
           <groupId>org.elasticsearch</groupId>
           <artifactId>elasticsearch</artifactId>
           <version>1.0.0</version>
       </dependency>
       <dependency>
           <groupId>com.spatial4j</groupId>
           <artifactId>spatial4j</artifactId>
           <version>0.4.1</version>
       </dependency>
       <dependency>
           <groupId>com.vividsolutions</groupId>
           <artifactId>jts</artifactId>
           <version>1.13</version>
           <exclusions>
               <exclusion>
                   <groupId>xerces</groupId>
                   <artifactId>xercesImpl</artifactId>
               </exclusion>
           </exclusions>
       </dependency>      
  1. Elasticsearch 是原始的官方包,

  2. spatial4j,jts 是引入未知搜尋的第三方包

使用API進行搜尋

(分場景進行讨論)

         elasticsearch的索引查詢主要分為query與filter 兩種:query與filter的主要差別在于query會對比對結果進行評分score,而filter隻會對結果做是否比對判斷,不做進一步處理。

         是以如果是強制過濾類的操作可以直接根據fiter過濾掉,而需要對模糊的得分進行score評分,優化索引查詢得分,最好做query查詢。

         query 由QueryBuilders生成,filter有FilterBuilders生成,

         每個下面索引查詢主要分為:termQuery,booleanQuery,matchQuery,rangeQuery,morelikeQuery,prefixQuery等等

                             過濾也主要分為termFilter,booleanFilter,matchFilter,rangeFilter,morelikeFilter,prefixFilter等等

        查詢的建立由SearchRequestBuilder 建立

1.按關鍵字搜尋。

       查詢:QueryBuilder qb = QueryBuilders.multiMatchQuery(
                       queryStr, "MERCHANT_NAME", "STREET_ADDRESS"
                   ).minimumShouldMatch("70%") ;       
QueryBuilder qb = QueryBuilders.boolQuery()
                     .must(termQuery("content", "test1"))    
                     .must(termQuery("content", "test4"))    
                     .mustNot(termQuery("content", "test2")) 
                     .should(termQuery("content", "test3"));      
        過濾:FilterBuilder filter = FilterBuilders.boolFilter()      
               .must(FilterBuilders.termFilter("MERCHANT_NAME",“寶得萊”));      
FilterBuilder filter = rangeFilter("age")   
                   .from("10")                           
                  .to("20")                             
                  .includeLower(true)                   
                  .includeUpper(false);                        

2.關鍵字搜尋+地理位置資訊搜尋。

FilterBuilder filter = geoDistanceRangeFilter("pin.location")   
    .point(40, -70)                                           
    .from("200km")                                             
    .to("400km")                                             
    .includeLower(true)                                         
    .includeUpper(false)                                       
    .optimizeBbox("memory")                                   
    .geoDistance(GeoDistance.ARC);              
QueryBuilder qb = QueryBuilders.multiMatchQuery(
        queryStr, "MERCHANT_NAME", "STREET_ADDRESS"
  ).minimumShouldMatch("70%") ;       
SearchRequestBuilder request = client.prepareSearch(index)       
.setSearchType(SearchType.QUERY_THEN_FETCH)       
.setScroll(new TimeValue(60000))       
.setQuery(qb.buildAsBytes())       
.setPostFilter(filter)       
.setTypes(merchant)      
.setFrom(start)      
.setSize(limit)       
.execute()      
.actionGet();       

3.搜尋并且排序。

SortBuilder sort = new FieldSortBuilder("_score").order(SortOrder.DESC).ignoreUnmapped(true);      
SearchRequestBuilder request = client.prepareSearch(index)      
.setSearchType(SearchType.QUERY_THEN_FETCH)      
.setQuery(qb.buildAsBytes())      
.setPostFilter(filter)      
.setTypes(merchant)      
.addSort(sort)       
.setFrom(start)      
.setSize(limit)       
.execute()       
.actionGet();       

4.設定搜尋權重(或者是索引時建立權重)

查詢時:

       a. 對特殊字段增權重重

QueryBuilder qb = QueryBuilders.multiMatchQuery(

queryStr,

"MERCHANT_NAME", "STREET_ADDRESS","PROVINCE_NAME","CITY_NAME","DISTRICT_NAME"

)

.field("MERCHANT_NAME",5f)          //添加字段權重 0-1 代表減弱,大于1代表增加預設1

.minimumShouldMatch("40%") ;

BoolFilterBuilder filter = this.parseFilter(mustParams);

filter = this.parseRangeFilter(filter,rangeParams);

SearchResponse scrollResp = null;

SearchRequestBuilder request = client.prepareSearch(index)

.setSearchType(SearchType.QUERY_THEN_FETCH)

.setScroll(new TimeValue(60000))

.setQuery(qb.buildAsBytes())

.setTypes(merchant)

.addHighlightedField("MERCHANT_NAME")

.setHighlighterPreTags("<B>" )

.setHighlighterPostTags("<B>" )

.setFrom(start)

.setSize(limit);

b. 通過需改score算法修改得分規則:

建立索引時:

    a. 建立索引時通過在資料json中添權重重boost:1.2 來提高資料索引權重,_boost預設=1,大于1是提高權重,小于1是降低權重。

      例:curl -XPOST http://localhost:9200/index/fulltext/19 -d' {_boost:11,"content":"公安部:中國駐洛杉矶領事館遭亞裔男子槍擊"} '  

    b. 通過建立mapping 是對某列單獨提高搜尋權重,設定boost。

      例: 

{ mappings: { laolaibao: { _all: { indexAnalyzer: "ik",  searchAnalyzer: "ik",  term_vector: "no",  store: "false" }, properties: { MERCHANT_NAME: { type: "string",  store: "no",  term_vector: "with_positions_offsets",  indexAnalyzer: "ik",  searchAnalyzer: "ik",  include_in_all: "true",  boost: 8 } } } } }      

http://songwie.com/articlelist/43

繼續閱讀