ElasticSearch入門-搜索如此簡單


搜索引擎我也不是很熟悉,但是數據庫還是比較了解。可以把搜索理解為數據庫的like功能的替代品。因為like有以下幾點不足:

第一、like的效率不行,在使用like時,一般都用不到索引,除非使用前綴匹配,才能用得上索引。但普通的需求並非前綴匹配。

第二、like的不能做到完全的模糊匹配。比如like '%化痰沖劑%'就不能把”化痰止咳沖劑“搜索出來。但是普通的用戶,需求就是這樣

第三、like無法根據匹配度進行排序。數據庫匹配某個關鍵字的記錄可能有好幾千,但是用戶只能看100條,數據庫往往返回用戶一些不關心的記錄。

種種原因導致搜索引擎的橫空出世。

為了說明ES的搜索AIP及搜索功能,我們需要先造點數據。

import org.elasticsearch.action.bulk.BulkRequestBuilder;  
import org.elasticsearch.action.bulk.BulkResponse;  
import org.elasticsearch.action.index.IndexRequestBuilder;  
import org.elasticsearch.client.Client;  
  
import com.donlianli.es.ESUtils;  
import com.donlianli.es.model.LogModel;  
  
public class BulkIndexTest {  
      
    public static void main(String[] args) {  
        String[] desc = new String[]{  
                "玉屏風口服液",  
                "清咽丸",  
                "四消丸",  
                "感冒清膠囊",  
                "人參歸脾丸",  
                  
                "人參健脾丸",  
                "明目地黃丸",  
                "小兒咳喘靈顆粒",  
                "小兒化痰止咳沖劑",  
                "雙黃連",  
                "六味地黃丸"  
        };  
        Client client = ESUtils.getClient();  
        int j= 0;  
        BulkRequestBuilder bulkRequest = client.prepareBulk();  
        for(int i=1000;i<1010;i++){  
            LogModel l = new LogModel();  
            l.setDesc(desc[j]);  
            j++;  
            String json = ESUtils.toJson(l);  
            IndexRequestBuilder indexRequest = client.prepareIndex("twitter", "tweet")  
            //指定不重復的ID        
            .setSource(json).setId(String.valueOf(i));  
            //添加到builder中  
            bulkRequest.add(indexRequest);  
        }  
          
        BulkResponse bulkResponse = bulkRequest.execute().actionGet();  
        if (bulkResponse.hasFailures()) {  
            // process failures by iterating through each bulk response item  
            System.out.println(bulkResponse.buildFailureMessage());  
        }  
    }  
}  

LogModel的定義見ElasticSearch入門-增刪改查(CRUD) 

我們插入了10條記錄到ES,別管ID是多少,只要不重就行。

下面,我們需要對LogModel的desc字段進行搜索。我們搜索一個最簡單的”丸“字,我們希望將所有帶丸字的記錄都篩選出來。

import org.elasticsearch.action.search.SearchResponse;  
import org.elasticsearch.client.Client;  
import org.elasticsearch.index.query.QueryBuilder;  
import org.elasticsearch.index.query.QueryBuilders;  
import org.elasticsearch.search.SearchHit;  
import org.elasticsearch.search.SearchHits;  
  
import com.donlianli.es.ESUtils;  
  
public class QuerySearchTest {  
    public static void main(String[] args) {  
        Client client = ESUtils.getClient();  
        QueryBuilder query = QueryBuilders.fieldQuery("desc", "丸");  
        SearchResponse response = client.prepareSearch("twitter")  
                .setTypes("tweet")  
                //設置查詢條件,  
                .setQuery(query)  
                .setFrom(0).setSize(60)  
                .execute()  
                .actionGet();  
        /** 
         * SearchHits是SearchHit的復數形式,表示這個是一個列表 
         */  
        SearchHits shs = response.getHits();  
        for(SearchHit hit : shs){  
            System.out.println("分數(score):"+hit.getScore()+", 業務描述(desc):"+  
                    hit.getSource().get("desc"));  
        }  
        client.close();  
    }  
  
}  

運行結果:

分數(score):2.97438, 業務描述(desc):四消丸  
分數(score):2.7716475, 業務描述(desc):清咽丸  
分數(score):2.6025825, 業務描述(desc):人參歸脾丸  
分數(score):2.6025825, 業務描述(desc):人參健脾丸  
分數(score):2.4251914, 業務描述(desc):明目地黃丸  

可以看到,搜索引擎已經將我們所有帶丸的記錄都篩選出來了。並且,字數最少的自動排在了最前面。是不是很智能。在完全沒有配置ES任何東西之前,就能使用搜索功能了。

 

 下面,我們再來試試搜索”小兒顆粒“,你猜會不會搜到記錄呢?運行結果:

分數(score):4.46157, 業務描述(desc):小兒咳喘靈顆粒  
分數(score):0.87699485, 業務描述(desc):小兒化痰止咳沖劑  

 嗯,不錯,雖然沒有完全匹配的,但相關記錄都已經出來了。

至此,使用ES替代數據庫的LIKE功能,基本上已經完成了。搜索的更多功能,探索ing。。。。

 

PS: ESUtils.getClient();就是一個靜態方法,創建了一個ES的客戶端。

public static Client getClient(){  
        Settings settings = ImmutableSettings.settingsBuilder()  
                //指定集群名稱  
                .put("cluster.name", "elasticsearch")  
                //探測集群中機器狀態  
                .put("client.transport.sniff", true).build();  
        /* 
         * 創建客戶端,所有的操作都由客戶端開始,這個就好像是JDBC的Connection對象 
         * 用完記得要關閉 
         */  
        Client client = new TransportClient(settings)  
        .addTransportAddress(new InetSocketTransportAddress("192.168.1.106", 9300));  
        return client;  
    }  

 

 

 

對這類話題感興趣?歡迎發送郵件至 donlianli@126.com;或者關注我的微信公眾號“猿界汪汪隊”
關於我:邯鄲人,擅長Java,Javascript,Extjs,oracle sql。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM