1. 程式人生 > >ElasticSearch搜尋引擎在JAVA中的簡單使用

ElasticSearch搜尋引擎在JAVA中的簡單使用

Elasticsearch常用操作和核心原理見文章:https://blog.csdn.net/sdksdk0/article/details/78469190
本文參照https://www.2cto.com/kf/201802/719374.html
一、引入ElasticSearch的jar

org.elasticsearch
elasticsearch
2.4.0


junit
junit
4.12


com.fasterxml.jackson.core
jackson-core
2.8.1


com.fasterxml.jackson.core
jackson-databind
2.8.1


com.fasterxml.jackson.core
jackson-annotations
2.8.1

二、建立文件型別實體Bean


package cn.elasticsearch.domain;

public class Article {
private Integer id;
private String title;
private String content;

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getTitle() {
    return title;
}

public void setTitle(String title) {
    this.title = title;
}

public String getContent() {
    return content;
}

public void setContent(String content) {
    this.content = content;
}

@Override
public String toString() {
    return "Article [id=" + id + ", title=" + title + ", content="
            + content + "]";
}

}
三、ElasticSearch中建立文件,自動建立索引
// 直接在ElasticSearch中建立文件,自動建立索引
@Test
public void demo1() throws IOException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

    // 建立物件要新增物件的JSON格式字串
    XContentBuilder builder = XContentFactory.jsonBuilder().startObject()
            .field("1", 1)
            .field("title", "ElasticSearch是一個基於Lucene的搜尋伺服器")
            .field("content", "它提供了一個分散式多使用者能力的全文搜尋引擎,基於RESTful web介面。Elasticsearch是用Java開發的,並作為Apache許可條款下的開放原始碼釋出,是當前流行的企業級搜尋引擎。設計用於雲端計算中,能夠達到實時搜尋,穩定,可靠,快速,安裝使用方便。")
            .endObject();

    // 建立文件物件
    client.prepareIndex("blog1", "article", "1").setSource(builder).get();

    // 關閉連線
    client.close();
}

四、QueryBuilders.matchAllQuery() 查詢所有
// 搜尋在ElasticSearch中建立的文件物件,使用QueryBuilders.matchAllQuery()查詢所有
@Test
public void demo2() throws UnknownHostException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

    // 手冊資料
    SearchResponse searchResponse = client
            .prepareSearch("blog1")
            .setTypes("article")
            .setQuery(QueryBuilders.matchAllQuery()).get();

    printSearchResponse(searchResponse);

    // 關閉連線
    client.close();
}

五、QueryBuilders.queryStringQuery() 分詞內容查詢
// 使用QueryBuilders.queryStringQuery(搜尋內容)進行分詞內容查詢
@Test
public void demo3() throws UnknownHostException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

    // 搜尋資料
    SearchResponse searchResponse = client
            .prepareSearch("blog1")
            .setTypes("article")
            .setQuery(QueryBuilders.queryStringQuery("全文")).get();

    printSearchResponse(searchResponse);

    // 關閉連線
    client.close();
}

六、QueryBuilders.wildcardQuery() 範圍分詞模糊查詢
// 使用QueryBuilders.wildcardQuery(“搜尋範圍:如title|content”,”查詢內容”)進行範圍分詞模糊查詢
// *表示任意字串 ?表示任意字元
// 查詢結果為0條,說明沒有詞條包含”全文”
@Test
public void demo4() throws UnknownHostException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

// 搜尋資料
SearchResponse searchResponse = client
        .prepareSearch("blog1")
        .setTypes("article")
        .setQuery(QueryBuilders.wildcardQuery("content", "*全文*")).get();

printSearchResponse(searchResponse);

// 關閉連線
client.close();

}
七、QueryBuilders.termQuery() 範圍詞條查詢
// 使用QueryBuilders.termQuery(“搜尋範圍:如title|content”,”查詢內容”)進行範圍詞條查詢
// 查詢結果為0條,說明沒有”搜尋”這個詞條
@Test
public void demo5() throws UnknownHostException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

// 搜尋資料
SearchResponse searchResponse = client
        .prepareSearch("blog2")
        .setTypes("article")
        .setQuery(QueryBuilders.termQuery("content", "搜")).get();

printSearchResponse(searchResponse);

// 關閉連線
client.close();

八、建立/刪除索引
// 索引操作 — 建立與刪除
@Test
public void demo6() throws UnknownHostException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

// 建立索引
client.admin().indices().prepareCreate("blog2").get();

// 刪除索引
//client.admin().indices().prepareDelete("blog2").get();

// 關閉連線
client.close();

}
九、建立對映
// 對映操作 — 建立
@Test
public void demo7() throws IOException, ExecutionException, InterruptedException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

// 新增對映
XContentBuilder builder = XContentFactory.jsonBuilder()
        .startObject()
        .startObject("article")
        .startObject("properties")
        .startObject("id").field("type", "integer").field("store", "yes").endObject()
        .startObject("title").field("type", "string").field("store", "yes").field("analyzer", "ik").endObject()
        .startObject("content").field("type", "string").field("store", "yes").field("analyzer", "ik").endObject()
        .endObject()
        .endObject()
        .endObject();

PutMappingRequest mapping = Requests.putMappingRequest("blog2")
        .type("article").source(builder);
client.admin().indices().putMapping(mapping).get();

// 關閉連線
client.close();

}
十、建立文件
// 文件操作 — 建立
@Test
public void demo8() throws IOException, ExecutionException, InterruptedException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

// 建立jackson解析物件
ObjectMapper objectMapper = new ObjectMapper();

for (int i = 1;i <= 100;i++){
    // 描述json 資料
    /*
     * {id:xxx, title:xxx, content:xxx}
     */
    Article article = new Article();
    article.setId(i);
    article.setTitle(i + "搜尋工作其實很難的");
    article.setContent(i + "我們希望我們的搜尋解決方案要快,我們希望有一個零配置和一個完全免費的搜尋模式,我們希望能夠簡單地使用JSON通過HTTP的索引資料,我們希望我們的搜尋伺服器始終可用,我們希望能夠一臺開始並擴充套件到數百,我們要實時搜尋,我們要簡單的多租戶,我們希望建立一個雲的解決方案。Elasticsearch旨在解決所有這些問題和更多的問題。");

    // 建立文件
    client.prepareIndex("blog2", "article", article.getId().toString())
            .setSource(objectMapper.writeValueAsString(article)).get();
}

// 關閉連線
client.close();

}
十一、分頁搜尋
// 分頁搜尋
@Test
public void demo11() throws UnknownHostException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

// 搜尋資料
SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog2")
        .setTypes("article")
        .setQuery(QueryBuilders.matchAllQuery());

// 通過SearchRequestBuilder的setFrom和setSize方法實現分頁
// 顯示第二頁的資料,每頁顯示20條
searchRequestBuilder.setFrom(2);
searchRequestBuilder.setSize(20);

SearchResponse searchResponse = searchRequestBuilder.get();

printSearchResponse(searchResponse);

// 關閉連線
client.close();

}
十二、高亮顯示
// 高亮顯示
@Test
public void demo12() throws IOException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

ObjectMapper objectMapper = new ObjectMapper();

// 搜尋資料
SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog2")
        .setTypes("article")
        .setQuery(QueryBuilders.termQuery("title","搜尋"));

// 高亮應用的內容
searchRequestBuilder.addHighlightedField("title"); // 對title欄位進行高亮
searchRequestBuilder.setHighlighterPreTags("<em>"); // 前置元素
searchRequestBuilder.setHighlighterPostTags("</em>"); // 後置元素

// 通過SearchRequestBuilder的setFrom和setSize方法實現分頁
// 顯示第二頁的資料,每頁顯示20條
searchRequestBuilder.setFrom(2).setSize(20);

SearchResponse searchResponse = searchRequestBuilder.get();

// 獲取命中次數,查詢結果又多少物件
SearchHits hits = searchResponse.getHits();
System.out.println("查詢結果有:" + hits.getTotalHits() + "條");
Iterator<searchhit> iterator = hits.iterator();
while (iterator.hasNext()) {
    SearchHit searchHit = iterator.next(); //每個查詢物件

    // 將高亮處理後的內容,替換原有高亮內容(原有內容,可能會出現顯示不全)
    Map<string,highlightfield> highlightFields = searchHit.getHighlightFields();
    HighlightField titleField = highlightFields.get("title");
    // 獲取到原有內容中的每個高亮顯示的集中的位置,fragment就是高亮片段
    Text[] fragments = titleField.fragments();
    String title = "";
    for (Text text : fragments){
        title += text;
    }

    // 通過ObjectMapper的readVallue將查詢結果轉換成Article物件
    Article article = objectMapper.readValue(searchHit.getSourceAsString(), Article.class);

    // 用高亮後內容,替換原有內容
    article.setTitle(title);

    System.out.println(article);
}

// 關閉連線
client.close();

}
十三、文件修改
// 文件操作 — 修改
@Test
public void demo9() throws IOException, ExecutionException, InterruptedException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

// 描述json 資料
/*
 * {id:xxx, title:xxx, content:xxx}
 */
Article article = new Article();
article.setId(2);
article.setTitle("搜尋工作其實也不難");
article.setContent("我們希望我們的搜尋解決方案要快,我們希望有一個零配置和一個完全免費的搜尋模式,我們希望能夠簡單地使用JSON通過HTTP的索引資料,我們希望我們的搜尋伺服器始終可用,我們希望能夠一臺開始並擴充套件到數百,我們要實時搜尋,我們要簡單的多租戶,我們希望建立一個雲的解決方案。Elasticsearch旨在解決所有這些問題和更多的問題。");

// 建立jackson解析物件
ObjectMapper objectMapper = new ObjectMapper();

// 修改文件 --- 方式一
//client.prepareUpdate("blog2", "article", article.getId().toString())
//        .setDoc(objectMapper.writeValueAsString(article)).get();

// 修改文件 --- 方式二
client.update(
        new UpdateRequest("blog2", "article", article.getId().toString())
                .doc(objectMapper.writeValueAsString(article))
).get();

// 關閉連線
client.close();

}
十四、文件刪除
// 文件操作 — 刪除
@Test
public void demo10() throws IOException, ExecutionException, InterruptedException {
// 建立ElasticSearch連線物件
Client client = getElasticSearchClient();

Article article = new Article();
article.setId(2);

// 刪除文件 --- 方式一
//client.prepareDelete("blog2", "article", article.getId().toString()).get();

// 刪除文件 --- 方式二
client.delete(
        new DeleteRequest("blog2", "article", article.getId().toString())
).get();

// 關閉連線
client.close();

}
完整程式碼:
package cn.elasticsearch.test;

import cn.elasticsearch.domain.Article;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.highlight.HighlightField;
import org.junit.Test;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutionException;

// ElasticSearch 測試程式
public class ElasticSearchTest {

// 直接在ElasticSearch中建立文件,自動建立索引
@Test
public void demo1() throws IOException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    // 建立物件要新增物件的JSON格式字串
    XContentBuilder builder = XContentFactory.jsonBuilder().startObject()
            .field("1", 1)
            .field("title", "ElasticSearch是一個基於Lucene的搜尋伺服器")
            .field("content", "它提供了一個分散式多使用者能力的全文搜尋引擎,基於RESTful web介面。Elasticsearch是用Java開發的,並作為Apache許可條款下的開放原始碼釋出,是當前流行的企業級搜尋引擎。設計用於雲端計算中,能夠達到實時搜尋,穩定,可靠,快速,安裝使用方便。")
            .endObject();

    // 建立文件物件
    client.prepareIndex("blog1", "article", "1").setSource(builder).get();

    // 關閉連線
    client.close();
}


// 搜尋在ElasticSearch中建立的文件物件,使用QueryBuilders.matchAllQuery()查詢所有
@Test
public void demo2() throws UnknownHostException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    // 手冊資料
    SearchResponse searchResponse = client
            .prepareSearch("blog1")
            .setTypes("article")
            .setQuery(QueryBuilders.matchAllQuery()).get();

    printSearchResponse(searchResponse);

    // 關閉連線
    client.close();
}

// 使用QueryBuilders.queryStringQuery(搜尋內容)進行分詞內容查詢
@Test
public void demo3() throws UnknownHostException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    // 搜尋資料
    SearchResponse searchResponse = client
            .prepareSearch("blog1")
            .setTypes("article")
            .setQuery(QueryBuilders.queryStringQuery("全文")).get();

    printSearchResponse(searchResponse);

    // 關閉連線
    client.close();
}

// 使用QueryBuilders.wildcardQuery("搜尋範圍:如title|content","查詢內容")進行範圍分詞模糊查詢
// *表示任意字串     ?表示任意字元
// 查詢結果為0條,說明沒有詞條包含"全文"
@Test
public void demo4() throws UnknownHostException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    // 搜尋資料
    SearchResponse searchResponse = client
            .prepareSearch("blog1")
            .setTypes("article")
            .setQuery(QueryBuilders.wildcardQuery("content", "*全文*")).get();

    printSearchResponse(searchResponse);

    // 關閉連線
    client.close();
}

// 使用QueryBuilders.termQuery("搜尋範圍:如title|content","查詢內容")進行範圍詞條查詢
// 查詢結果為0條,說明沒有"搜尋"這個詞條
@Test
public void demo5() throws UnknownHostException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    // 搜尋資料
    SearchResponse searchResponse = client
            .prepareSearch("blog2")
            .setTypes("article")
            .setQuery(QueryBuilders.termQuery("content", "搜")).get();

    printSearchResponse(searchResponse);

    // 關閉連線
    client.close();
}

// 索引操作 --- 建立與刪除
@Test
public void demo6() throws UnknownHostException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    // 建立索引
    client.admin().indices().prepareCreate("blog2").get();

    // 刪除索引
    //client.admin().indices().prepareDelete("blog2").get();

    // 關閉連線
    client.close();
}

// 對映操作 --- 建立
@Test
public void demo7() throws IOException, ExecutionException, InterruptedException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    // 新增對映
    XContentBuilder builder = XContentFactory.jsonBuilder()
            .startObject()
            .startObject("article")
            .startObject("properties")
            .startObject("id").field("type", "integer").field("store", "yes").endObject()
            .startObject("title").field("type", "string").field("store", "yes").field("analyzer", "ik").endObject()
            .startObject("content").field("type", "string").field("store", "yes").field("analyzer", "ik").endObject()
            .endObject()
            .endObject()
            .endObject();

    PutMappingRequest mapping = Requests.putMappingRequest("blog2")
            .type("article").source(builder);
    client.admin().indices().putMapping(mapping).get();

    // 關閉連線
    client.close();
}

// 文件操作 --- 建立
@Test
public void demo8() throws IOException, ExecutionException, InterruptedException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    // 建立jackson解析物件
    ObjectMapper objectMapper = new ObjectMapper();

    for (int i = 1;i <= 100;i++){
        // 描述json 資料
        /*
         * {id:xxx, title:xxx, content:xxx}
         */
        Article article = new Article();
        article.setId(i);
        article.setTitle(i + "搜尋工作其實很難的");
        article.setContent(i + "我們希望我們的搜尋解決方案要快,我們希望有一個零配置和一個完全免費的搜尋模式,我們希望能夠簡單地使用JSON通過HTTP的索引資料,我們希望我們的搜尋伺服器始終可用,我們希望能夠一臺開始並擴充套件到數百,我們要實時搜尋,我們要簡單的多租戶,我們希望建立一個雲的解決方案。Elasticsearch旨在解決所有這些問題和更多的問題。");

        // 建立文件
        client.prepareIndex("blog2", "article", article.getId().toString())
                .setSource(objectMapper.writeValueAsString(article)).get();
    }

    // 關閉連線
    client.close();
}

// 分頁搜尋
@Test
public void demo11() throws UnknownHostException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    // 搜尋資料
    SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog2")
            .setTypes("article")
            .setQuery(QueryBuilders.matchAllQuery());

    // 通過SearchRequestBuilder的setFrom和setSize方法實現分頁
    // 顯示第二頁的資料,每頁顯示20條
    searchRequestBuilder.setFrom(2);
    searchRequestBuilder.setSize(20);

    SearchResponse searchResponse = searchRequestBuilder.get();

    printSearchResponse(searchResponse);

    // 關閉連線
    client.close();
}

// 高亮顯示
@Test
public void demo12() throws IOException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    ObjectMapper objectMapper = new ObjectMapper();

    // 搜尋資料
    SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog2")
            .setTypes("article")
            .setQuery(QueryBuilders.termQuery("title","搜尋"));

    // 高亮應用的內容
    searchRequestBuilder.addHighlightedField("title"); // 對title欄位進行高亮
    searchRequestBuilder.setHighlighterPreTags("<em>"); // 前置元素
    searchRequestBuilder.setHighlighterPostTags("</em>"); // 後置元素

    // 通過SearchRequestBuilder的setFrom和setSize方法實現分頁
    // 顯示第二頁的資料,每頁顯示20條
    searchRequestBuilder.setFrom(2).setSize(20);

    SearchResponse searchResponse = searchRequestBuilder.get();

    // 獲取命中次數,查詢結果又多少物件
    SearchHits hits = searchResponse.getHits();
    System.out.println("查詢結果有:" + hits.getTotalHits() + "條");
    Iterator<searchhit> iterator = hits.iterator();
    while (iterator.hasNext()) {
        SearchHit searchHit = iterator.next(); //每個查詢物件

        // 將高亮處理後的內容,替換原有高亮內容(原有內容,可能會出現顯示不全)
        Map<string,highlightfield> highlightFields = searchHit.getHighlightFields();
        HighlightField titleField = highlightFields.get("title");
        // 獲取到原有內容中的每個高亮顯示的集中的位置,fragment就是高亮片段
        Text[] fragments = titleField.fragments();
        String title = "";
        for (Text text : fragments){
            title += text;
        }

        // 通過ObjectMapper的readVallue將查詢結果轉換成Article物件
        Article article = objectMapper.readValue(searchHit.getSourceAsString(), Article.class);

        // 用高亮後內容,替換原有內容
        article.setTitle(title);

        System.out.println(article);
    }

    // 關閉連線
    client.close();
}

// 文件操作 --- 修改
@Test
public void demo9() throws IOException, ExecutionException, InterruptedException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    // 描述json 資料
    /*
     * {id:xxx, title:xxx, content:xxx}
     */
    Article article = new Article();
    article.setId(2);
    article.setTitle("搜尋工作其實也不難");
    article.setContent("我們希望我們的搜尋解決方案要快,我們希望有一個零配置和一個完全免費的搜尋模式,我們希望能夠簡單地使用JSON通過HTTP的索引資料,我們希望我們的搜尋伺服器始終可用,我們希望能夠一臺開始並擴充套件到數百,我們要實時搜尋,我們要簡單的多租戶,我們希望建立一個雲的解決方案。Elasticsearch旨在解決所有這些問題和更多的問題。");

    // 建立jackson解析物件
    ObjectMapper objectMapper = new ObjectMapper();

    // 修改文件 --- 方式一
    //client.prepareUpdate("blog2", "article", article.getId().toString())
    //        .setDoc(objectMapper.writeValueAsString(article)).get();

    // 修改文件 --- 方式二
    client.update(
            new UpdateRequest("blog2", "article", article.getId().toString())
                    .doc(objectMapper.writeValueAsString(article))
    ).get();

    // 關閉連線
    client.close();
}

// 文件操作 --- 刪除
@Test
public void demo10() throws IOException, ExecutionException, InterruptedException {
    // 建立ElasticSearch連線物件
    Client client = getElasticSearchClient();

    Article article = new Article();
    article.setId(2);

    // 刪除文件 --- 方式一
    //client.prepareDelete("blog2", "article", article.getId().toString()).get();

    // 刪除文件 --- 方式二
    client.delete(
            new DeleteRequest("blog2", "article", article.getId().toString())
    ).get();

    // 關閉連線
    client.close();
}

// 遍歷列印查詢後的結果
private void printSearchResponse(SearchResponse searchResponse) {
    // 獲取命中次數,查詢結果又多少物件
    SearchHits hits = searchResponse.getHits();
    System.out.println("查詢結果有:" + hits.getTotalHits() + "條");
    Iterator<searchhit> iterator = hits.iterator();
    while (iterator.hasNext()) {
        SearchHit searchHit = iterator.next(); //每個查詢物件
        System.out.println(searchHit.getSourceAsString()); //獲取字串格式並列印
        System.out.println("title:" + searchHit.getSource().get("title"));
    }
}

// 獲取ElasticSearcch Client物件
private Client getElasticSearchClient() throws UnknownHostException {
    return TransportClient
            .builder()
            .build()
            .addTransportAddress(
                    new InetSocketTransportAddress(
                            InetAddress.getByName("127.0.0.1"), 9300));
}

}