zoukankan      html  css  js  c++  java
  • 使用JAVA操作ElasticSearch(Java API 和Spring Data ElasticSearch)

    Java操作ElasticSearch

    Java API

    我的ElasticSearch集群的版本是6.2.4,导入elasticsearch相关的maven依赖也是6.2.4,不同版本的api可能会有差异

    一:maven依赖

    复制代码
       <!--elasticsearch核心依赖-->
            <dependency>
                <groupId>org.elasticsearch</groupId>
                <artifactId>elasticsearch</artifactId>
                <version>6.2.4</version>
            </dependency>
            <!--elasticsearch客户端-->
            <dependency>
                <groupId>org.elasticsearch.client</groupId>
                <artifactId>transport</artifactId>
                <version>6.2.4</version>
            </dependency>
            <!--日志-->
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-to-slf4j</artifactId>
                <version>2.9.1</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.24</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-simple</artifactId>
                <version>1.7.21</version>
            </dependency>
    
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--单元测试-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>compile</scope>
            </dependency>
            <!--实体转json-->
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.10.2</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.10.2</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>2.10.2</version>
            </dependency>
    
            <!--实体类简化工具-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.18</version>
            </dependency>
    复制代码

    2.单元测试的共有方法

    复制代码
      TransportClient client;
    
        @Before
        //创建连接
        public void connection() throws UnknownHostException {
            //创建客户端连接对象
            //参数为configelasticsearch.yml中对应的值 也就是集群名称
            Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
            client = new PreBuiltTransportClient(settings);
            client.addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.118.3"), 9300));
            client.addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.118.4"), 9300));
            client.addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.118.5"), 9300));
        }
    
    
    
      @After
        //释放资源
        public void close() {
            client.close();
        }
    
    
    
        //遍历结果集
        public void iteratorSearchHit(SearchHits searchHits) {
            System.out.println("符合查询条件有:" + searchHits.getTotalHits() + "条");
            //获取迭代器
            Iterator<SearchHit> iterator = searchHits.iterator();
            System.out.println("开始进行遍历------------------------------");
            while (iterator.hasNext()) {
                //获取每个查询对象
                SearchHit searchHit = iterator.next();
                //获取字符串类型并进行打印
                System.out.println(searchHit.getSourceAsString());
                Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
                System.out.println("符合搜索条件的标题是:=======" + sourceAsMap.get("title"));
                /*   for (Map.Entry<String,Object> map:sourceAsMap.entrySet()){
                    System.out.println("===================================");
                    System.out.println(map.getKey());
                    System.out.println(map.getValue());
                }
                */
            }
        }
    复制代码

    3.常规操作

    复制代码
       @Test
        //创建索引库
        public void createIndex() {
            //索引名成必须小写
            client.admin().indices().prepareCreate("myindex1").get();
        }
    
        @Test
        //添加映射
        public void mapping() throws IOException, ExecutionException, InterruptedException {
            XContentBuilder builder = XContentFactory.jsonBuilder().startObject()
                    .startObject("type1")
                    .startObject("properties")
                    .startObject("id")
                    .field("type", "integer")
                    .field("store", "true")
                    .endObject()
                    .startObject("title")
                    .field("type", "text")
                    .field("store", "true")
                    .field("analyzer", "ik_smart")
                    .endObject()
                    .startObject("content")
                    .field("type", "text")
                    .field("store", "true")
                    .field("analyzer", "ik_smart")
                    .endObject()
                    .endObject()
                    .endObject()
                    .endObject();
            PutMappingRequest mappingRequest = Requests.putMappingRequest("myindex1")
                    .type("type1")
                    .source(builder);
            client.admin().indices().putMapping(mappingRequest).get();
        }
    
        @Test
        //给myindex1的type1创建文档
        public void createDocument() throws IOException {
            XContentBuilder xContentBuilder = XContentFactory.jsonBuilder();
            xContentBuilder.startObject()
                    .field("id", 1)
                    .field("title", "ElasticSearch是一个基于Lucene的搜索服务器")
                    .field("content", "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用 Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到 实时搜索,稳定,可靠,快速,安装使用方便。")
                    .endObject();
            //参数1:索引名 2:类型 3:id
            client.prepareIndex("myindex1", "type1", "1").setSource(xContentBuilder).get();
    
        }
    
        @Test
        //通过实体转json创建文档
        public void jsonDocument() throws JsonProcessingException {
            Type1 type1 = new Type1();
            type1.setId(2);
            type1.setTitle("通过实体转json创建文档");
            type1.setContent("通过创建实体的方式,将实体转json");
            ObjectMapper objectMapper = new ObjectMapper();
            client.prepareIndex("myindex1", "type1", type1.getId().toString())
                    .setSource(objectMapper.writeValueAsString(type1).getBytes(), XContentType.JSON)
                    .get();
        }
    
        @Test
        //关键词查询
        public void termQuery() {
            //设置搜索条件,目标索引库,目标类型,目标域
            SearchResponse searchResponse = client.prepareSearch("myindex1")
                    .setTypes("type1")
                    .setQuery(QueryBuilders.termQuery("content", "实体")).get();
            SearchHits hits = searchResponse.getHits();
            iteratorSearchHit(hits);
        }
    
        @Test
        //字符串查询
        public void stringQuery() {
            //设置搜索条件,目标索引库,目标类型
            SearchResponse searchResponse = client.prepareSearch("myindex1")
                    .setTypes("type1")
                    .setQuery(QueryBuilders.queryStringQuery("搜索实体")).get();
            SearchHits hits = searchResponse.getHits();
            iteratorSearchHit(hits);
        }
    
        @Test
        //根据文档ID进行查询
        public void idQuery() {
            SearchResponse searchResponse = client.prepareSearch("myindex1")
                    .setQuery(QueryBuilders.idsQuery("type1").addIds("2"))
                    .get();
            iteratorSearchHit(searchResponse.getHits());
        }
    
        //分页之前的操作,批量添加文档
        @Test
        public void batchInsert() throws JsonProcessingException {
            Type1 type1;
            for (int i = 1; i <= 50; i++) {
                type1 = new Type1();
                type1.setId(i);
                type1.setTitle(i + "通过实体转json创建文档");
                type1.setContent(i + "通过创建实体的方式,将实体转json");
                ObjectMapper objectMapper = new ObjectMapper();
                client.prepareIndex("myindex1", "type1", type1.getId().toString())
                        .setSource(objectMapper.writeValueAsString(type1).getBytes(), XContentType.JSON)
                        .get();
            }
        }
    
        //搜索文档并分页显示
        @Test
        public void pageDocument() {
            SearchResponse searchResponse = client.prepareSearch("myindex1")
                    .setTypes("type1")
                    .setQuery(QueryBuilders.matchAllQuery())
                    //setFrom():从第几条开始检索,默认是0。
                    // setSize():每页最多显示的记录数默认是十
                    .setFrom(0)
                    .setSize(5)
                    .get();
            iteratorSearchHit(searchResponse.getHits());
        }
    
    
        //模拟搜索结果高亮显示
        @Test
        public void highlight() {
            //设置查询条件
            SearchRequestBuilder searchRequestBuilder = client.prepareSearch("myindex1")
                    .setTypes("type1")
                    .setQuery(QueryBuilders.termQuery("title", "实体"));
            //高亮设置
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            //开头的标签信息
            highlightBuilder.preTags("<font style='color:red'>");
            //结尾的标签
            highlightBuilder.postTags("</font>");
            highlightBuilder.field("title");
            searchRequestBuilder.highlighter(highlightBuilder);
            SearchResponse searchResponse = searchRequestBuilder.get();
            Iterator<SearchHit> iterator = searchResponse.getHits().iterator();
            while (iterator.hasNext()) {
                SearchHit hit = iterator.next();
                System.out.print("正常String方式打印文档搜索内容====");
                System.out.println(hit.getSourceAsString());
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                //遍历集合,输出高亮数据
                //方式1
                Text[] titles = highlightFields.get("title").getFragments();
                for (Text str : titles) {
                    System.out.println(str);
                }
            }
        }
    复制代码

    Spring Data ElasticSearch

    Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。 Spring Data可以极大的简化JPA的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。

    笔者的ElasticSearch集群的版本是6.2.4,导入spring-data-elasticsearch的maven依赖也是3.1.5.RELEASE,不同版本的api可能会有差异

    一:准备maven依赖

    复制代码
     <!--elasticsearch核心依赖-->
            <dependency>
                <groupId>org.elasticsearch</groupId>
                <artifactId>elasticsearch</artifactId>
                <version>6.2.4</version>
            </dependency>
            <!--elasticsearch客户端-->
            <dependency>
                <groupId>org.elasticsearch.client</groupId>
                <artifactId>transport</artifactId>
                <version>6.2.4</version>
            </dependency>
            <!--日志-->
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-to-slf4j</artifactId>
                <version>2.9.1</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.24</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-simple</artifactId>
                <version>1.7.21</version>
            </dependency>
    
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--单元测试-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>compile</scope>
            </dependency>
           
            <!--实体类简化工具-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.18</version>
            </dependency>
    
            <!--springframework-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>5.2.3.RELEASE</version>
            </dependency>
            <!--spring-data-elasticsearch-->
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-elasticsearch</artifactId>
                <version>3.1.5.RELEASE</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.elasticsearch.plugin</groupId>
                        <artifactId>transport‐netty4‐client</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    复制代码

    二:创建实体

    复制代码
    package com.yjc.entity;
    
    import lombok.Data;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.elasticsearch.annotations.Document;
    import org.springframework.data.elasticsearch.annotations.Field;
    import org.springframework.data.elasticsearch.annotations.FieldType;
    
    //lombok相当于get,set,toSting等一系列方法
    @Data
    //代表文档对象(索引库,类型)
    @Document(indexName = "myindex2",type = "article")
    public class Article {
        //文档主键,唯一
        @Id
        //store是否存储(默认false),index是否分词(默认true),type类型
        @Field(store = true,index = false,type = FieldType.Integer)
        private Integer id;
        //下面配置代表 进行存储并以ik_smart方式分词,(默认开启分词)保持的类型为text,进行查询的时候按照ik_smart方式进行分词
        @Field(store = true,analyzer ="ik_smart",searchAnalyzer = "ik_smart",type = FieldType.Text)
        private String title;
        //下面配置代表 进行存储并以ik_smart方式分词,保持的类型为text,进行查询的时候按照ik_smart方式进行分词
        @Field(store = true,analyzer ="ik_smart",searchAnalyzer = "ik_smart",type = FieldType.Text)
        private String content;
    }
    复制代码

    三:创建DAO和Service

    ArticleDao
    复制代码
    package com.yjc.dao;
    
    import com.yjc.entity.Article;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository
    /**
     * ElasticsearchRepository<要操作的实体类,ID在实体类中类型>
     * */
    public interface ArticleDao extends ElasticsearchRepository<Article,Integer> {
        //根据标题查询
        List<Article> findByTitle(String condition);
        //根据标题查询(含分页)
        Page<Article> findByTitle(String condition, Pageable pageable);
        //根据id
        List<Article> findById(String condition);
    }
    复制代码
    ArticleService
    复制代码
    package com.yjc.service;
    
    import com.yjc.entity.Article;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    
    import java.util.List;
    
    public interface ArticleService {
        //添加
        void save(Article article);
        //删除
        void delete(Article article);
        //查询全部
        Iterable<Article> findAll();
        //分页查询
        Page<Article> findAll(Pageable pageable);
    
        //根据标题查询
        List<Article> findByTitle(String condition);
        //根据标题查询(含分页)
        Page<Article> findByTitle(String condition, Pageable pageable);
        //根据内容搜索并分页
        List<Article> findById(String condition);
    }
    复制代码
    ArticleServiceImpl
    复制代码
    package com.yjc.service.impl;
    
    import com.yjc.dao.ArticleDao;
    import com.yjc.entity.Article;
    import com.yjc.service.ArticleService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.stereotype.Service;
    import java.util.List;
    
    @Service
    public class ArticleServiceImpl implements ArticleService {
       @Autowired
        ArticleDao articleDao;
        @Override
        public void save(Article article) {
            articleDao.save(article);
        }
    
        @Override
        public void delete(Article article) {
            articleDao.delete(article);
        }
    
        @Override
        public Iterable<Article> findAll() {
            return articleDao.findAll();
        }
    
        @Override
        public Page<Article> findAll(Pageable pageable) {
            return articleDao.findAll(pageable);
        }
    
        @Override
        public List<Article> findByTitle(String condition) {
            return articleDao.findByTitle(condition);
        }
    
        @Override
        public Page<Article> findByTitle(String condition, Pageable pageable) {
            return articleDao.findByTitle(condition,pageable);
        }
    
        @Override
        public List<Article> findById(String condition) {
            return articleDao.findById(condition);
        }
    }
    复制代码

    四:创建Spring的核心配置文件

    applicationContext.xml,注意更换命名空间

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
    xsi:schemaLocation=" http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/data/elasticsearch
    http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd "> <!--创建包扫描器,扫描Dao,自动创建实例--> <elasticsearch:repositories base-package="com.yjc.dao"/> <!--扫描Service--> <context:component-scan base-package="com.yjc.service"/> <!--配置es的连接--> <elasticsearch:transport-client id="client" cluster-nodes="192.168.118.3:9300" cluster-name="elasticsearch"/> <!--es模板对象--> <bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate"> <constructor-arg name="client" ref="client"/> </bean> </beans>
    复制代码

    五:测试

    复制代码
    package com.yjc.test;
    
    import com.yjc.entity.Article;
    import com.yjc.service.ArticleService;
    import org.elasticsearch.client.transport.TransportClient;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import java.util.List;
    
    
    @RunWith(SpringJUnit4ClassRunner.class)
    //启动单元测试的时候加载的配置文件
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class SpringDataESTest {
        @Autowired
        ArticleService articleService;
    
        //注入连接对象
        @Autowired
        TransportClient client;
        //注入模板对象
        @Autowired
        ElasticsearchTemplate elasticsearchTemplate;
    
        @Test
        //创建索引
        public void createIndex() {
            //配置在实体类中已经配置好了,直接创建并添加映射
            elasticsearchTemplate.createIndex(Article.class);
            elasticsearchTemplate.putMapping(Article.class);
        }
    
        @Test
        //保存文档
        public void saveArticle() {
            Article article = new Article();
            article.setId(101);
            article.setTitle("测试SpringData ElasticSearch");
            article.setContent("Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操 作,将原始操作elasticSearch的客户端API 进行封装 
    " + " Spring Data为Elasticsearch Elasticsearch项目提供集成搜索引擎");
            articleService.save(article);
        }
    
        @Test
        //修改文档
        public void update() {
            Article article = new Article();
            article.setId(100);
            article.setTitle("修改SpringData ElasticSearch");
            article.setContent("修改Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操 作,将原始操作elasticSearch的客户端API 进行封装 
    " + " Spring Data为Elasticsearch Elasticsearch项目提供集成搜索引擎");
            articleService.save(article);
        }
        @Test
        //删除文档
        public  void delete(){
            Article article = new Article();
            article.setId(100);
            articleService.delete(article);
        }
    
        @Test
        //分页查询
        public void findAllPage(){
            Pageable pageable=PageRequest.of(0,10);
            Page<Article> all = articleService.findAll(pageable);
            for (Article article:all.getContent()){
                System.out.println(article);
            }
    
        }
        @Test
        //带条件查询
        public  void findByTitle(){
            List<Article> articles = articleService.findByTitle("测试");
            for (Article article:articles){
                System.out.println(article);
            }
        }
        @Test
        //待条件查询加分页
        public void findByTitlePage(){
            Pageable pageable=PageRequest.of(0,1);
            Page<Article> articles = articleService.findByTitle("引擎", pageable);
            for (Article article:articles.getContent()){
                System.out.println(article);
            }
        }
    
        @Test
        //根据id进行查询
        public void findByContent(){
            List<Article> articles = articleService.findById("100");
            for (Article article:articles){
                System.out.println(article);
            }
        }
    }
    复制代码
  • 相关阅读:
    open()函数与读写文件
    vim编辑器常用操作
    strip()函数---去除字符串首尾字符
    Python中字符串转义的用法
    shell中内置字段的分隔符IFS
    shell中整数变量自增用法
    shell中EOF的用法
    shell变量字符串截取
    shell中的“数组”
    年终总结:想的多了就该敷衍性得记录一下
  • 原文地址:https://www.cnblogs.com/rzbwyj/p/12396196.html
Copyright © 2011-2022 走看看