ElasticSearch和Idea的联合,源方法,不使用springdata框架

本文档详细介绍了如何在 IntelliJ IDEA 中使用 Maven 创建非骨架工程,学习 Elasticsearch 的原生 Java API。从设置 JDK 版本、添加依赖到创建索引、设置 mapping、添加 document、搜索数据、分页查询以及高亮显示,每个步骤都有清晰的代码示例。通过 JUnit 测试用例展示了如何连接 ES 集群、创建索引、添加 JSON 数据、使用 QueryBuilder 进行搜索和高亮等操作。

【1】创建maven工程,不需要骨架,普通的即可,因为我们是为了学习es在idea上怎么使用,而不是开发项目。

【2】导入jar包坐标

         这里很多东西中央仓库都没有,而且加载又慢,顺便提一嘴,把maven的config文件夹下的conf-setting.xml中添加阿里的云端

        

 记得要把jdk手动设置成1.9,因为idea默认用1.5

<properties>
        <maven.compiler.source>1.9</maven.compiler.source>
        <maven.compiler.target>1.9</maven.compiler.target>
</properties>
<dependencies>
    <dependency>
        <groupId>org.elasticsearch</groupId>
        <artifactId>elasticsearch</artifactId>
        <version>5.6.8</version>
    </dependency>
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>transport</artifactId>
        <version>5.6.8</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>
    </dependency>
</dependencies>

【3】我们先学习下原生的es在java中如何使用(不适用springdata框架)

         获取连接步骤:

                1.创建一个setting对象,用来设置我们的es-cluster集群名称,来获取到我们的es集群

                2.创建一个TranspotClient对象,他有一个字类PreBuiltTransportClient,可以把我们的setting写入。获取到cilent客户端对象。

                3.用client.addTransportAddress添加我们的主机地址和端口号,这里的端口号不是http的端口号了,而是TCP

                4.最后使用client,创建一个索引库

                5.关闭索引库

 @Test
    public void createIndex() throws Exception{
//    编写测试方法实现创建索引库
//		1、创建一个Settings对象,相当于是一个配置信息。主要配置集群的名称。
        //put中这只集群的name,获取我们配置好的cluster集群
        Settings settings=Settings.builder().put("cluster.name","my-elasticsearch").build();
//      2、创建一个客户端Client对象
        //除了设置集群的名称,还需要设置我们的端口号,这里注意端口号不是http,而是tcp
        //为了防止某个节点挂了,所以三个全设置上。
        TransportClient  client=new PreBuiltTransportClient(settings);
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9301));
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9302));
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9303));
//		3、使用client对象创建一个索引库
        client.admin().indices().prepareCreate("hello").get();//设置索引库名称并且创建,get是执行这个索引操作
//		4、关闭client对象
        client.close();
    }

【4】索引库创建了,自然也要设置mapping,也就是我们的域,一共有两种方式可以把我们的mapping的json格式弄出来。一种是拼接json字符串,另一种是用XcontentBuilder方法,也会转成json。不过不管用哪一种,都非常麻烦

         先来一张用postman创建的mapping,这样两个对比比较好理解

        startObject就代表{

        写了参数的startObject(参数)就代表:参数{

        endobject就代表}

        field就代表域中的属性

 XContentBuilder builder= XContentFactory.jsonBuilder()
                .startObject()  //相当于{
                    .startObject("article")  //相当于type的名字 article:{
                        .startObject("properties") //properties:{
                            .startObject("id") //id:{
                                .field("type","long")
                                .field("store",true)
                            .endObject()//}
                            .startObject("title") //title:{
                                .field("type","text")
                                .field("store",true)
                                .field("index",true)
                                .field("analyzer","ik_smart")
                             .endObject()
                            .startObject("content") //content:{
                                .field("type","text")
                                .field("store",true)
                                .field("index",true)
                                .field("analyzer","ik_smart")
                            .endObject()
                         .endObject()
                    .endObject()
                .endObject();
 //4使用client向es服务器发送mapping信息,参数1:设置指定的索引,参数2:设置我们需要映射的tpye,参数三:把我们的json数据传入
client.admin().indices().preparePutMapping("hello").setType("article").setSource(builder).get();

 最后也是用client.admin().indices来创建mapping,需要设置索引库,索引库的type。

【5】添加document,也就是域中对应的内容

         大家可以发现,原生的es在idea中,都离不开三部,

         就是1.setting,2.transportClient获取client,3.client.addTransportAddress设置主机和端口号

         所以我们大可把这三部,提出去,用@Before标注,这样就会在其他方法执行前把我们需要的client加载好。

         依旧是使用xContentBuilder来写我们的json数据,区别就是最后发送请求的时候,只用prepareIndex(canshu1,canshu2,canshu3),参数分别是索引库,type,和documentID。

@Test
    public void addDocument() throws Exception{
        Settings settings=Settings.builder().put("cluster.name","my-elasticsearch").build();
        TransportClient client=new PreBuiltTransportClient(settings);
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9301))
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9302))
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9303));
        XContentBuilder builder=XContentFactory.jsonBuilder()
                .startObject()
                    .field("id",1)
                    .field("title","这是用java编写的es索引")
                    .field("content","即麻烦又不好用")
                .endObject();
        client.prepareIndex("hello","article","1").setSource(builder).get();//这里的id是_id,就是文档的id
        client.close();

    }

 【6】当然我们既然用了idea,就不需要这么麻烦的去弄document的json格式,有的是方法可以帮我们的数据转成json,之前在做网页的时候,从后端传过来的数据,不就是需要转成json格式的嘛。多了两个jar包而已,总比自己写这么多语句好。

 <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.6.7</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.0</version>
        </dependency>

          有了json的jar包,我就创建一个pojo类不就好了,这个类里写上和field对应的参数。

          在我们存document的时候就可以直接设置这个pojo类的参数,然后利用ObjectMapper把类转成json字符串。

@Test
    public void addArticleDocument2() throws  Exception{
        Article article=new Article();
        article.setId(2l);
        article.setTitle("这是用json转换器把java-->json");
        article.setContent("比用Xcontent拼接简单");
        ObjectMapper mapper=new ObjectMapper();
        String s = mapper.writeValueAsString(article);
        //下面的部分可以拿出去,都是重复内容
        Settings settings=Settings.builder().put("cluster.name","my-elasticsearch").build();
        TransportClient client=new PreBuiltTransportClient(settings);
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9301))
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9302))
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9303));
        client.prepareIndex("hello","article","2").setSource(s, XContentType.JSON).get();
        client.close();
    }

【7】搜索数据

        1 把重复的代码拿出来

@Before
    public void init() throws Exception{
        Settings settings=Settings.builder().put("cluster.name","my-elasticsearch").build();
        client=new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9301))
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9302))
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9303));
    }

        2.因为查询数据只有一个QueryBuilder的查询信息的差异,其他的都一样,所以我们把一样的代码也封装成一个方法,到时候直接调用即可       


    private void search(QueryBuilder queryBuilder) throws Exception{
        //执行查询,第一个参数设置查询的索引,第二个设置type
        SearchResponse searchResponse = client.prepareSearch("hello").setTypes("article").setQuery(queryBuilder).get();
        //取查询结果,获取结果集
        SearchHits hits = searchResponse.getHits();
        //取查询结果的总记录数
        long totalHits = hits.getTotalHits();
        System.out.println("总共查询到"+totalHits+"条数据");
        //查询结果列表
        for (SearchHit hit : hits) {
            //打印文档对象,以json的格式输出
            System.out.println(hit.getSourceAsString());
            //用map键值对拿出属性数据
            Map<String, Object> source = hit.getSource();
            System.out.println("id为:"+source.get("id")+","+"\n"+"title为:"+source.get("title")+","+"\n"+"content为:"+source.get("content"));
           System.out.println("--------------------");
        }
        //关闭client
        client.close();

        QueryBuiler一共可以创建出3中查询对象,根据term查询,根据queryString查询,根据id查询

 @Test
    public void  searchById() throws Exception{
        //ducumentID可以同时定义多个
        QueryBuilder queryBuilder= QueryBuilders.idsQuery().addIds("1","2");
        search(queryBuilder);
    }
    @Test
    public void searchByTerm() throws Exception{
        //参数1为搜索的域,参数2为搜索的关键词
        QueryBuilder queryBuilder=QueryBuilders.termQuery("title","转换器");
        search(queryBuilder);
    }
    @Test
    public void searchByQuerySrting() throws Exception{
        //defaultFiled不写也行
        QueryBuilder queryBuilder=QueryBuilders.queryStringQuery("转换器").defaultField("title");
        search(queryBuilder);
    }

【8】分页查询,我们一般默认情况下,只会搜索出10条数据,也就是如果我们搜索到了100条数据,也只会显示10条

         所以需要进行分页,来设定我们每页显示几条数据,这个需要在我们的searchResponse中设置,因为这个使获取返回的数据的。

        只要加上setFrom()从第几页查询,setSize(),每页查询几条数据。其他的都不变

 SearchResponse searchResponse = client.prepareSearch("hello").setTypes("article").setQuery(queryBuilder)
                //设置分页信息
                .setFrom(0)
                .setSize(5)
                .get();

【9】高亮查询

         就是把我们搜索的关键字标注出来,并且显示结果,下面标红字的就是高亮显示。

        

         我们需要做的就是1.创建一个HighlightBuilder对象,然后这个对象设置高亮显示的域。

         preTag就是在高亮关键字的前面添加tag标签,postTag自然就是在后面。

         依然是在searchResponse返回的数据上设置高亮。

         结果集hits里也有提供获取高亮信息的方法:getHighlightFields

        得到的是一个map集合,其中String代表的是咱们的域,HighlightField类是我们域中高亮的document数据。

 private void search(QueryBuilder queryBuilder,String highLightField) throws Exception{
        //创建一个HighLightBuilder,设置高亮显示
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.field(highLightField).preTags("<em>").postTags("<em>");
        //执行查询,第一个参数设置查询的索引,第二个设置type
        SearchResponse searchResponse = client.prepareSearch("hello").setTypes("article").setQuery(queryBuilder)
                //设置分页信息以及高亮显示
                .setFrom(0)
                .setSize(5)
                .highlighter(highlightBuilder)
                .get();
        //取查询结果,获取结果集
        SearchHits hits = searchResponse.getHits();
        //取查询结果的总记录数
        long totalHits = hits.getTotalHits();
        System.out.println("总共查询到"+totalHits+"条数据");
        //查询结果列表
            System.out.println("-----高亮显示结果");
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            System.out.println(highlightFields);
            HighlightField field = highlightFields.get(highLightField);
            Text[] fragments = field.getFragments();
            if (fragments!=null){
                System.out.println(fragments[0].toString());
            }
            System.out.println("--------------------");
        }
        //关闭client
        client.close();

最后我们来看一下,高亮的数据和我们普通的数据获取有什么区别,高亮只会拿到我们设置的域中的符合条件的数据。并且把关键字用我们指定的标签包起来了;

 @Test
    public void searchByTerm() throws Exception{
        //参数1为搜索字段,参数2为搜索的关键词
        QueryBuilder queryBuilder=QueryBuilders.termQuery("title","转换器");
        search(queryBuilder,"title");
    }
{"id":18,"title":"这是用json转换器把java-->json18","content":"比用Xcontent拼接简单18"}
id为:18,
title为:这是用json转换器把java-->json18,
content为:比用Xcontent拼接简单18

-----高亮显示结果
{title=[title], fragments[[这是用json<em>转换器<em>把java-->json18]]}
这是用json<em>转换器<em>把java-->json18



--------------------



{"id":77,"title":"这是用json转换器把java-->json77","content":"比用Xcontent拼接简单77"}
id为:77,
title为:这是用json转换器把java-->json77,
content为:比用Xcontent拼接简单77

-----高亮显示结果
{title=[title], fragments[[这是用json<em>转换器<em>把java-->json77]]}
这是用json<em>转换器<em>把java-->json77

### 如何在 IntelliJ IDEA使用 Spring 框架集成 Elasticsearch #### 创建项目并引入依赖项 为了在 IntelliJ IDEA使用 Spring 框架集成 Elasticsearch 开发应用程序,首先需要创建一个新的 Spring Boot 工程。确保已经配置好了 Java 环境以及安装了 IntelliJ IDEA 必要的插件如 Spring Assistant[^3]。 接着,在 `pom.xml` 文件中添加所需的 Maven 依赖项以支持 Spring Data Elasticsearch 功能: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> ``` 这一步骤使得能够轻松地与 Elasticsearch 数据库交互而无需手动编写大量底层代码[^1]。 #### 设计实体类仓库接口 定义一个表示文档模型的 POJO 类(例如 User),该类应标注为 `@Document` 并指定索引名称;同时还需要创建相应的 Repository 接口继承自 `ElasticsearchRepository<User, String>` 来封装 CRUD 操作逻辑。 ```java import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; @Document(indexName = "users", type = "_doc") public class User { @Id private String id; private String name; // getter and setter methods... } ``` 对于仓库部分,则只需声明如下所示简单的接口即可获得基本的数据访问能力: ```java import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; public interface UserRepository extends ElasticsearchRepository<User, String> {} ``` #### 编写服务层业务逻辑 接下来就是实现具体的应用程序功能了。通常会有一个 Service 层负责调用上述 Repositories 提供的方法完成特定的任务,比如保存新记录、检索符合条件的结果集等操作。 ```java @Service public class UserService { @Autowired private final UserRepository userRepository; public List<User> findAllUsers() { return userRepository.findAll(); } // Other service methods... } ``` #### 测试与验证 最后可以通过单元测试或者 Postman 等工具向 RESTful API 发送 HTTP 请求来进行最终的功能检验。确保一切正常之后便可以在生产环境中部署运行这个基于 Spring Boot 的微服务架构下的 ElasticSearch 应用了[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hpeacheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值