原创

本文将介绍如何使用java调用elasticsearch的api

本文将介绍如何使用java调用elasticsearch的api

1、获取client连接

复制代码
package com.test.elasticsearch;

import java.net.InetAddress;
import java.net.UnknownHostException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.junit.After;
import org.junit.Before;

/**

  • 抽象的Junit测试
  • @author xuwenjin
    */
    public abstract class AbstractJunitTest {

    protected Logger logger = LogManager.getLogger(this.getClass());

    protected Client client;

    /**

    • 获取一个客户端
      */
      @SuppressWarnings("resource")
      @Before
      public void getClient() throws UnknownHostException {
      Settings settings = Settings.builder().put("cluster.name", "xwj").build();

      TransportAddress transportAddress = new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300);
      client = new PreBuiltTransportClient(settings).addTransportAddress(transportAddress);
      }

      /**

    • 关闭连接
      */
      @After
      public void close() {
      client.close();
      }

}
复制代码

2、新增、删除索引

复制代码
package com.test.elasticsearch;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.junit.Test;

/**

  • 索引操作测试
  • @author xuwenjin
    */
    public class IndexTest extends AbstractJunitTest {

    /**

    • 判断是否存在该索引
    • @param indexName
    • 索引名称
    • @return
      */
      public boolean isIndexExists(String indexName) {
      IndicesExistsRequestBuilder builder = client.admin().indices().prepareExists(indexName);
      IndicesExistsResponse res = builder.get();
      return res.isExists();
      }

      /**

    • 5.*之后,把string字段设置为了过时字段,引入text,keyword字段
    • keyword:存储数据时候,不会分词建立索引
    • text:存储数据时候,会自动分词,并生成索引(这是很智能的,但在有些字段里面是没用的,所以对于有些字段使用text则浪费了空间)。
      *
    • 如果在添加分词器的字段上,把type设置为keyword,则创建索引会失败
      */
      public XContentBuilder getIndexSource() throws IOException {
      XContentBuilder source = XContentFactory.jsonBuilder().startObject().startObject("test_type2")

           .startObject("properties")
           // code字段
           .startObject("code").field("type", "text").field("index", true).field("fielddata", true).endObject()
           // 名称字段
           .startObject("name").field("type", "keyword").field("store", false).field("index", true).endObject()
           // 信息字段
           .startObject("info").field("type", "keyword").field("store", false).field("index", true).endObject()
           // 主要内容字段
           .startObject("content").field("type", "text").field("store", true).field("index", true).field("analyzer", "ik_max_word").endObject()
           .startObject("my_title").field("type", "keyword").field("store", true).field("index", true).endObject()
           .startObject("you_title").field("type", "keyword").field("store", true).field("index", true).endObject()
           .startObject("isDelete").field("type", "boolean").field("store", true).field("index", true).endObject()
           .startObject("age").field("type", "long").field("store", true).field("index", true).endObject()
      
           .endObject().endObject().endObject();
      

      return source;
      }

      /**

    • 创建索引
      */
      @Test
      public void createIndex() {
      try {

       if (isIndexExists("test_index2")) {
           logger.info("索引对象已经存在,无法创建!");
           return;
       }
       CreateIndexRequestBuilder builder = client.admin().indices().prepareCreate("test_index2");
       // 直接创建Map结构的setting
       Map<String, Object> settings = new HashMap<>();
       settings.put("number_of_shards", 5); // 分片数
       settings.put("number_of_replicas", 1); // 副本数
       settings.put("refresh_interval", "10s"); // 刷新间隔
       builder.setSettings(settings);
      
       builder.addMapping("test_type2", getIndexSource());
      
       CreateIndexResponse res = builder.get();
       logger.info(res.isAcknowledged() ? "索引创建成功!" : "索引创建失败!");
      

      } catch (Exception e) {

       logger.error("创建索引失败!", e);
      

      }
      }

      /**

    • 删除索引
      */
      @Test
      public void deleteIndex() {
      try {
       if (!isIndexExists("test_index2")) {
           logger.info("索引对象已经不存在,无法删除!");
           return;
       }
       DeleteIndexRequestBuilder builder = client.admin().indices().prepareDelete("test_index2");
       DeleteIndexResponse res = builder.get();
       logger.info(res.isAcknowledged() ? "删除索引成功!" : "删除索引失败!");
      
      } catch (Exception e) {
       logger.error("删除索引失败!", e);
      
      }
      }

}
复制代码

  执行createIndex方法之后,可以在elasticsearch-head中看到该索引被创建

3、向ES中添加数据

复制代码
package com.test.elasticsearch;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

/**

  • 向ES中添加数据
  • @author xuwenjin
    */
    public class AddDataTest extends AbstractJunitTest {

    // private static final String INDEX = "test_index1";
    // private static final String TYPE = "test_type1";
    private static final String INDEX2 = "test_index2";
    private static final String TYPE2 = "test_type2";

    @Test
    public void saveData() {

     try {
         Map<String, Object> source = new HashMap<String, Object>();
         source.put("code", "01");
         source.put("name", "科技");
         source.put("info", "中共十九大");
         source.put("content", "中共十九大");
         source.put("my_title", "我的标题12323abcd");
         source.put("you_title", "你的标题1efg");
         source.put("isDelete", true);
         source.put("age", 16);
    
         Map<String, Object> source2 = new HashMap<String, Object>();
         source2.put("code", "02");
         source2.put("name", "新闻");
         source2.put("info", "中国周恩来");
         source2.put("content", "中国周恩来");
         source2.put("my_title", "我的标题235325abcd");
         source2.put("you_title", "你的标题346565efg");
         source2.put("isDelete", false);
         source2.put("age", 17);
    
         Map<String, Object> source3 = new HashMap<String, Object>();
         source3.put("code", "03");
         source3.put("name", "科学技术");
         source3.put("info", "用友建筑大武汉");
         source3.put("content", "用友建筑大武汉");
         source3.put("my_title", "我的标题65845abcd");
         source3.put("you_title", "你的标题237678efg");
         source3.put("isDelete", false);
         source3.put("age", 18);
    
         Map<String, Object> source4 = new HashMap<String, Object>();
         source4.put("code", "04");
         source4.put("name", "快手视频");
         source4.put("info", "中国特色社会主义");
         source4.put("content", "中国特色社会主义");
         source4.put("my_title", "我的标题6789dfgf");
         source4.put("you_title", "你的标题67458sdfdf");
         source4.put("isDelete", true);
         source4.put("age", 19);
    
         Map<String, Object> source5 = new HashMap<String, Object>();
         source5.put("code", "05");
         source5.put("name", "科技视频");
         source5.put("info", "最美天安门");
         source5.put("content", "最美天安门");
         source5.put("my_title", "132445dfgdfg");
         source5.put("you_title", "32557fdgfg");
         source5.put("isDelete", true);
         source5.put("age", 20);
    
         Map<String, Object> source6 = new HashMap<String, Object>();
         source6.put("code", "06");
         source6.put("name", "最快的技术");
         source6.put("info", "美丽大武汉");
         source6.put("content", "美丽大武汉");
         source6.put("my_title", "356thjmkj345");
         source6.put("you_title", "4gfjgfjg4523");
         source6.put("isDelete", false);
         source6.put("age", 21);
    
         client.prepareIndex(INDEX2, TYPE2).setId("1").setSource(source).get();
         client.prepareIndex(INDEX2, TYPE2).setId("2").setSource(source2).get();
         client.prepareIndex(INDEX2, TYPE2).setId("3").setSource(source3).get();
         client.prepareIndex(INDEX2, TYPE2).setId("4").setSource(source4).get();
         client.prepareIndex(INDEX2, TYPE2).setId("5").setSource(source5).get();
         client.prepareIndex(INDEX2, TYPE2).setId("6").setSource(source6).get();
    
     } catch (Exception e) {
         logger.error("保存数据失败!", e);
     }
    

    }

}
复制代码

4、简单查询、删除数据

复制代码
package com.test.elasticsearch;

import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;

/**

  • 简单查询数据、删除数据
  • @author xuwenjin
    */
    public class SimpleQueryTest extends AbstractJunitTest {

    private static final String INDEX = "test_index1"; // 索引
    private static final String TYPE = "test_type1"; // 类型

    @Test
    public void queryObject() {

     try {
         GetResponse res = client.prepareGet(INDEX, TYPE, "1").get();
         if (res.isExists()) {
             logger.info("根据ID查询到数据,主要内容:" + res.getSource().get("content"));
         } else {
             logger.info("根据ID未查询到数据!");
         }
     } catch (Exception e) {
         logger.error("根据ID查询记录失败!", e);
     }
    

    }

    @Test
    public void queryList() {

     try {
         String key = "周恩来";
         QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(key, "name", "content");
    
         SearchResponse res = client.prepareSearch().setIndices(INDEX).setTypes(TYPE).setQuery(queryBuilder).get();
    
         logger.info("查询到的总记录个数为:" + res.getHits().getTotalHits());
         for (int i = 0; i < res.getHits().getTotalHits(); i++) {
             logger.info("第" + (i + 1) + "条记录主要内容为:" + res.getHits().getAt(i).getSource().get("content"));
         }
     } catch (Exception e) {
         logger.error("查询列表失败!", e);
     }
    

    }

    @Test
    public void deleteData() {

     try {
         DeleteResponse res = client.prepareDelete(INDEX, TYPE, "1").get();
    
         logger.info("删除动作执行状态:" + res.status());
     } catch (Exception e) {
         logger.error("删除数据失败!", e);
     }
    

    }

}
复制代码

5、复杂查询 

复制代码
package com.test.elasticsearch;

import java.util.Map;

import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.junit.Test;

/**

  • 复杂查询,使用QueryBuilder进行bool查询
  • @author xuwenjin
    */
    public class QueryBuilderTest extends AbstractJunitTest {

    private static final String INDEX2 = "test_index2";
    private static final String TYPE2 = "test_type2";

    public String text = "科技视频";

    /**

    • 单个精确值查找(termQuery)
      */
      @Test
      public void termQuery() {
      QueryBuilder queryBuilder = QueryBuilders.termQuery("code", "01");
      queryBuilder = QueryBuilders.termQuery("isDelete", true);
      queryBuilder = QueryBuilders.termQuery("my_title", "我的标题12323abcd");
      searchFunction(queryBuilder);
      }

      /**

    • 多个值精确查找(termsQuery)
    • 一个查询相匹配的多个value
      */
      @Test
      public void termsQuery() {
      QueryBuilder queryBuilder = QueryBuilders.termsQuery("code", "01", "03", "04");
      searchFunction(queryBuilder);
      }

      /**

    • 查询相匹配的文档在一个范围(rangeQuery)
      */
      @Test
      public void rangeQuery() {
      QueryBuilder queryBuilder = QueryBuilders

           .rangeQuery("code") // 查询code字段
           .from("02")
           .to("04")
           .includeLower(true) // 包括下界
           .includeUpper(false);// 不包括上界
      

      searchFunction(queryBuilder);
      }

      /**

    • 查询相匹配的文档在一个范围(prefixQuery)
      */
      @Test
      public void prefixQuery() {
      QueryBuilder queryBuilder = QueryBuilders.prefixQuery("my_title", "我的");
      searchFunction(queryBuilder);
      }

      /**

    • 通配符检索(wildcardQuery)
    • 值使用用通配符,常用于模糊查询
    • 匹配具有匹配通配符表达式( (not analyzed )的字段的文档。 支持的通配符:
    • *,它匹配任何字符序列(包括空字符序列)
    • ?,它匹配任何单个字符。
    • 请注意,此查询可能很慢,因为它需要遍历多个术语。 为了防止非常慢的通配符查询,通配符不能以任何一个通配符或?开头。 /
      @Test
      public void wildcardQuery() {
      QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("my_title", "6789");
      queryBuilder = QueryBuilders.wildcardQuery("my_title", "*345");
      queryBuilder = QueryBuilders.wildcardQuery("name", "?闻");
      searchFunction(queryBuilder);
      }

      /**

    • 正则表达式检索(regexpQuery) 不需要^、$
      */
      @Test
      public void regexpQuery() {
      QueryBuilder queryBuilder = QueryBuilders.regexpQuery("my_title", "我的.+f");
      searchFunction(queryBuilder);
      }

      /**

    • 使用模糊查询匹配文档查询(fuzzyQuery)
      */
      @Test
      public void fuzzyQuery() {
      QueryBuilder queryBuilder = QueryBuilders.fuzzyQuery("name", "科技");
      searchFunction(queryBuilder);
      }

      /**

    • 类型检索(typeQuery)
    • 查询该类型下的所有数据
      */
      @Test
      public void typeQuery() {
      QueryBuilder queryBuilder = QueryBuilders.typeQuery(TYPE2);
      searchFunction(queryBuilder);
      }

      /**

    • Ids检索, 返回指定id的全部信息 (idsQuery)
    • 在idsQuery(type)方法中,也可以指定具体的类型
      */
      @Test
      public void idsQuery() {
      QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1", "4", "10");
      searchFunction(queryBuilder);
      }

      /** 全文检索 **/

      /**

    • 单个匹配 (matchQuery)
    • 感觉跟termQuery效果一样
      */
      @Test
      public void matchQuery() {
      QueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "科技");
      searchFunction(queryBuilder);
      }

      /**

    • 查询匹配所有文件 (matchAllQuery)
      */
      @Test
      public void matchAllQuery() {
      QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
      searchFunction(queryBuilder);
      }

      /**

    • 匹配多个字段, field可以使用通配符(multiMatchQuery)
      /
      @Test
      public void multiMatchQuery() {
      QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("132445dfgdfg", "my_title", "name", "you_title");
      queryBuilder = QueryBuilders.multiMatchQuery("132445dfgdfg", "
      title"); //字段使用通配符
      searchFunction(queryBuilder);
      }

      /**

    • 字符串检索(queryString)
    • 一个使用查询解析器解析其内容的查询。
    • query_string查询提供了以简明的简写语法执行多匹配查询 multi_match queries ,布尔查询 bool queries ,提升得分 boosting ,模糊
    • 匹配 fuzzy matching ,通配符 wildcards ,正则表达式 regexp 和范围查询 range queries 的方式。
    • 支持参数达10几种
      /
      @Test
      public void queryString() {
      QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("
      技术"); //通配符查询
      // QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("我的.+f");
      searchFunction(queryBuilder);
      }

      /**

    • must 相当于and,就是都满足
    • should 相当于or,满足一个或多个
    • must_not 都不满足
      /
      @Test
      public void testQueryBuilder2() {
      // "科技视频"分词的结果是"科技", "视频", "频"
      BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
      // queryBuilder.must(QueryBuilders.wildcardQuery("name", "
      科技"));
      // queryBuilder.must(QueryBuilders.wildcardQuery("info", "
      "));
      // queryBuilder.must(QueryBuilders.wildcardQuery("content", "
      美丽*"));

      queryBuilder.should(QueryBuilders.wildcardQuery("name", "科技"));
      queryBuilder.should(QueryBuilders.wildcardQuery("info", ""));
      queryBuilder.should(QueryBuilders.wildcardQuery("content", "美丽"));
      queryBuilder.minimumShouldMatch(2); // 最少匹配数

      // queryBuilder.mustNot(QueryBuilders.wildcardQuery("name", "科技"));
      // queryBuilder.mustNot(QueryBuilders.wildcardQuery("info", ""));
      // queryBuilder.mustNot(QueryBuilders.wildcardQuery("content", "美丽"));
      searchFunction(queryBuilder);
      }

      /**

    • 查询遍历抽取
    • 查询结果是根据分值排序(从大到小)
    • @param queryBuilder
      */
      private void searchFunction(QueryBuilder queryBuilder) {
      SearchRequestBuilder requestBuilder = client.prepareSearch().setIndices(INDEX2).setTypes(TYPE2)
           .setScroll(new TimeValue(60000)).setQuery(queryBuilder);
      
      SearchResponse response = requestBuilder.setFrom(0).setSize(100).execute().actionGet();
      System.out.println("--------------查询结果:----------------------");
      for (SearchHit hit : response.getHits()) {
       System.out.println("分值:" + hit.getScore()); // 相关度
       Map<String, Object> map = hit.getSource();
       for (String sKey : map.keySet()) {
           System.out.println(sKey + ": " + map.get(sKey));
       }
       System.out.println("--------------");
      
      }
      System.out.println("-----------------------------------");
      }

}
复制代码

  本文的源码地址:https://github.com/xuwenjin/xwj_repo/tree/master/elasticsearch

  参考资料:
  解析Elasticsearch的SearchRequestBuilder的query类型
  Elasticsearch检索分类深入详解—基础篇

  SearchRequestBuilder常用方法说明

正文到此结束
该篇文章的评论功能已被站长关闭
本文目录