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));
}

}

猜你喜欢

转载自blog.csdn.net/xiaolong2230/article/details/81316226