ElasticSearch(二)

本文详细介绍了如何使用JavaAPI和SpringDataES操作ElasticSearch,包括创建索引、设置映射、添加文档、查询方式如根据_id、term、queryString查询,以及分页和高亮显示。此外,还探讨了SpringDataES的配置、DAO接口的自定义查询方法命名规则,以及拆词查询的实现。
摘要由CSDN通过智能技术生成

JavaAPI操作ES服务器

创建空项目,添加modles(maven管理),导入依赖,进行操作ES。

<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>
  1. 创建索引
    @Test
    //1.创建索引
    public void test1() throws Exception{
        // 创建Client连接对象,告知连接的集群的名称和通信ip和端口
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        TransportClient 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));
        //创建名称为demo1的索引
        client.admin().indices().prepareCreate("demo1").get();
        //释放资源
        client.close();
    }
  1. 设置mapping映射(json中第一个数据为type名称,第二个properties为type中的字段)
      @Test
    //2.创建映射
    public void test3() throws Exception {
        // 创建Client连接对象
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        TransportClient 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));

        // 添加映射
        /**
         * 格式:
         * "mappings" : {
         "article" : {
         "dynamic" : "false",
         "properties" : {
         "id" : { "type" : "string" },
         "content" : { "type" : "string" },
         "author" : { "type" : "string" }
         }
         }
         }
         */
        XContentBuilder builder = XContentFactory.jsonBuilder()
                .startObject()
                    .startObject("hello1")
                        .startObject("properties")
                            .startObject("id")
                            .field("type", "integer")
                            .field("store", true)
                            .endObject()
                            .startObject("title")
                            .field("type", "string")
                            .field("store", true)
                            .field("analyzer", "ik_smart")
                            .endObject()
                            .startObject("content")
                            .field("type", "string")
                            .field("store", true)
                            .field("analyzer", "ik_smart")
                            .endObject()
                        .endObject()
                     .endObject()
                .endObject();
        // 创建映射
        client.admin().indices()
                .preparePutMapping("demo1")//指定索引名
                .setType("hello1")//设置type名,需要和builder保持一致
                .setSource(builder)//设置mapping内容
                .get();//执行操作
        //释放资源
        client.close();
    }
  1. 添加文档

1)创建Article实体

public class Article {
	private Integer id;
	private String title;
	private String content;
    getter/setter...
}

2)添加fastjson坐标

<!--json转换工具-->
<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
        </dependency>
      @Test
	//3.创建文档(通过实体转json)
    public void test5() throws Exception {
        // 创建Client连接对象
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));
        // 描述json 数据
        //{id:xxx, title:xxx, content:xxx}
        Hello hello = new Hello();
        hello.setId(2);
        hello.setTitle("搜索工作其实很快乐");
        hello.setContent("我们希望我们的搜索解决方案要快,我们希望有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP的索引数据,我们希望我们的搜索服务器始终可用,我们希望能够一台开始并扩展到数百,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。Elasticsearch旨在解决所有这些问题和更多的问题。");
        //将对象装换为json
        Object o = JSON.toJSON(hello);
        String s = o.toString();
        System.out.println(o);

        // 建立文档,此处设置对象的id为_id
        client.prepareIndex("demo1", "hello1", hello.getId().toString())
                .setSource(s.getBytes(), XContentType.JSON)
                .get();

        //释放资源
        client.close();
    }

查询:通过QueryBuilder来设置查询方式和查询的条件
抽取连接es服务器获取client客户端的操作

private TransportClient client;
    @Before
    public void creatConn(){
        //1、创建es客户端连接对象
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        try {
            client = new PreBuiltTransportClient(settings)
                   .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

    }
  1. 根据_id查询
  @Test
    //4.2根据_id进行查询,id可以为多个
    public void testQueryId() throws Exception{
        //2、设置搜索条件
        QueryBuilder queryBuilder=QueryBuilders.idsQuery().addIds("1").addIds("2");
        SearchResponse searchResponse = client.prepareSearch("demo1")
                .setTypes("hello1")
                .setQuery(queryBuilder).get();

        //3、遍历搜索结果数据
        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"));
        }
        //4、释放资源
        client.close();
    }
  1. 根据term查询
  @Test
    //4.1根据关键字进行查询term
    public void testTermQuery() throws Exception{
        //1、创建es客户端连接对象
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));

        //2、设置搜索条件
        QueryBuilder queryBuilder = QueryBuilders.termQuery("content", "搜索");
        SearchResponse searchResponse = client.prepareSearch("demo1")
                .setTypes("hello1")
                .setQuery(queryBuilder).get();

        //3、遍历搜索结果数据
        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"));
        }
        //4、释放资源
        client.close();
    }
  1. 根据queryString查询:多条件查询先拆词后对词进行搜索满足其中一个即可
    queryString 多条件查询

•会对查询条件进行分词。

•然后将分词后的查询条件和词条进行等值匹配

•默认取并集(OR)

•可以指定多个查询字段

  @Test
    //4.3根据字符串进行搜索。拆词进行匹配。
    public void testStringQuery() throws Exception{
        //1、创建es客户端连接对象
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));

        //2、设置搜索条件
        QueryBuilder queryBuilder=QueryBuilders.queryStringQuery("搜索");//分词器拆成了搜和索进行查找
        //quertyBuilder.field("mapping列名").field("mapping列名")用来指定要搜索的列
        SearchResponse searchResponse = client.prepareSearch("demo1")
                .setTypes("hello1")
                .setQuery(queryBuilder).get();
        //3、遍历搜索结果数据
        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"));
        }
        //4、释放资源
        client.close();
    }
  1. 查询分页
    @Test
    //5.1创建文档(通过实体转json)
    public void insertMany() throws Exception {
        for (int i = 0; i < 50; i++) {
            //描述json 数据
            //{id:xxx, title:xxx, content:xxx}
            Hello hello = new Hello();
            hello.setId(i);
            hello.setTitle("分页数据搜加索"+i);
            hello.setContent("分页内容搜"+i);
            //将对象装换为json
            Object o = JSON.toJSON(hello);
            String s = o.toString();
            System.out.println(o);
            // 建立文档,此处设置对象的id为_id
            client.prepareIndex("demo1", "hello1", hello.getId().toString())
                    .setSource(s.getBytes(), XContentType.JSON)
                    .get();
        }
        //释放资源
        client.close();
    }

    @Test
    //5.2分页查询数据
    public void testStringQuery1() throws Exception{
        //1、创建es客户端连接对象
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));

        //2、设置搜索条件
        QueryBuilder queryBuilder=QueryBuilders.queryStringQuery("搜索");//分词器拆成了搜和索进行查找
        SearchResponse searchResponse = client.prepareSearch("demo1")
                .setTypes("hello1")
                .setQuery(queryBuilder)
                //不设置默认展示10条数据
                .setFrom(0)
                .setSize(5)
                .get();
        //3、遍历搜索结果数据
        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"));
        }
        //4、释放资源
        client.close();
    }
  1. 查询结果高亮显示
    实现原理在关键词的前后加上了一个h5标签来进行高亮显示
    在进行关键字搜索时,搜索出的内容中的关键字会显示不同的颜色,称之为高亮
    在这里插入图片描述
   @Test
    //6.高亮查询
    public void toOpen() throws Exception{
        //设置高亮数据
        HighlightBuilder hiBuilder=new HighlightBuilder();
        hiBuilder.preTags("<font style='color:red'>");//设置高亮前标签
        hiBuilder.field("title");//设置高亮显示的字段
        hiBuilder.postTags("</font>");//设置高亮结束标签
        // 搜索数据
        QueryBuilder queryBuilder= QueryBuilders.termQuery("title", "显示");
        SearchResponse searchRequestBuilder = client.prepareSearch("demo1")
                .setTypes("hello1")
                .setQuery(queryBuilder)
                .highlighter(hiBuilder)
                .get();
        //获取查询结果集
        SearchHits searchHits = searchRequestBuilder.getHits();
        System.out.println("共搜到:"+searchHits.getTotalHits()+"条结果!");
        //遍历结果
        for(SearchHit hit:searchHits){
            System.out.println("String方式打印文档搜索内容:");
            System.out.println(hit.getSourceAsString());
            System.out.println("Map方式打印高亮内容");
            System.out.println(hit.getHighlightFields());

            System.out.println("遍历高亮集合,打印高亮片段:");
            Text[] text = hit.getHighlightFields().get("title").getFragments();
            for (Text str : text) {
                System.out.println(str);//高亮内容的样式
            }
        }
        //释放资源
        client.close();
    }

SpringDataES操作ES服务器

  1. 导入Spring Data ElasticSearch坐标
<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>

        <!--引入SpringData ES的依赖-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.0.5.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.elasticsearch.plugin</groupId>
                    <artifactId>transport-netty4-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--测试-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.4.RELEASE</version>
        </dependency>
        <!--json转换工具-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
        </dependency>
  1. 创建applicationContext.xml配置文件,引入elasticsearch命名空间
    配置集群连接信息、配置SpringDataES提供的模板对象、配置扫描dao所对应的包
<?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="dao"/>

    <!-- 配置elasticSearch的连接 -->
        <!-- 配置elasticSearch的连接 -->
    <elasticsearch:transport-client id="client" cluster-nodes="localhost:9301" cluster-name="my-elasticsearch"/>

    <!-- ElasticSearch模版对象 -->
    <bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
        <constructor-arg name="client" ref="client"></constructor-arg>
    </bean>	
</beans>

当项目为SpringBoot项目时,待补充?
3. 配置实体
基于spring data elasticsearch注解配置索引、映射和实体的关系

其中,注解解释如下:
@Document(indexName="blob3",type="article"):
    indexName:索引的名称(必填项)
    type:索引的类型
@Id:主键的唯一标识
@Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    index:是否设置分词
    analyzer:存储时使用的分词器
    searchAnalyze:搜索时使用的分词器
    store:是否存储
    type: 数据类型
//指定索引、文档、文档的字段信息。
//@Document 文档对象 (索引信息、文档类型 )
@Document(indexName = "demo2",type = "hello2")
public class Hello {
    //@Id 文档主键 唯一标识
    @Id//此处得id和_id的值默认保持一致
    //@Field 每个文档的字段配置(类型、是否分词、是否存储、分词器 )
    @Field(store=true, index = false,type = FieldType.Integer)
    private Integer id;
    @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    private String title;
    @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    private String content;
//get\set\toString
  1. 编写dao接口(也称Repository仓库)
@Repository
public interface HelloRepository extends ElasticsearchRepository<Hello, Integer> {
    //自定义方法,按照命名规则命名即可,SpringDataES自动实现
    /**根据content或者title来查询*/
    List<Hello> findByContentOrTitle(String content,String title);


    /**根据content来查询*/
    List<Hello> findByContent(String content);
}
  1. 编写测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringDataESTest {

    @Autowired
    private HelloRepository repository;

    /*@Autowired
    private TransportClient client;*/

    @Autowired
    private ElasticsearchTemplate template;

    /**
     * 创建索引和映射
     */
    @Test
    public void createIndex() {
        template.createIndex(Hello.class);
        //上边创建索引中包含映射
        // elasticsearchTemplate.putMapping(Hello.class);
    }

    /**
     * 添加文档
     */
    @Test
    public void createDocument() {
        Hello hello = new Hello();
        hello.setId(6);
        hello.setTitle("SpringData");
        hello.setContent("data内容被我修改了");
        //将文档写入索引库
        repository.save(hello);
    }

    /**
     * 根据_id删除文档
     */
    @Test
    public void deleteDocument() {
        repository.deleteById(5);
    }


    /**
     * 更新文档:根据id来删除旧的插入新的
     */
    @Test
    public void updateDocument() {
        Hello hello = new Hello();
        hello.setId(5);
        hello.setTitle("SpringData");
        hello.setContent("内容+修改了");
        //将文档写入索引库
        repository.save(hello);
    }


    /**
     * 查询所有
     */
    @Test
    public void findAll() {
        Iterable<Hello> all = repository.findAll();
        // all.forEach(a-> System.out.println(a));
        Iterator<Hello> iterator = all.iterator();
        while (iterator.hasNext()) {
            Hello next = iterator.next();
            System.out.println(next);
        }
    }

    /**
     * 根据_id查询单个
     */
    @Test
    public void findById() {
        Optional<Hello> byId = repository.findById(1);
        Hello hello = byId.get();
        System.out.println(hello);
    }

    /**
     * 自定义查询方法
     */
    @Test
    public void findByMy() {
        List<Hello> byContentOrTitle = repository.findByContentOrTitle("修改了", "数据");
        //stream流遍历
        byContentOrTitle.stream().forEach(System.out::println);
    }

    /**
     * 查询之拆词词间关系为and
     * 某个词不是数据中内容则会查询为空null
     */
    @Test
    public void findByContentAnd() {
        //对内容进行拆分,拆分后关系为and,数据中没有”我“这个词,故查询失败
        List<Hello> byContentOrTitle = repository.findByContent("我修改了内容");
        //stream流遍历
        byContentOrTitle.stream().forEach(System.out::println);
    }

    /**
     * 此方法常用
     * 查询之拆词词间关系变为or
     */
    @Test
    public void findByContentOr() {
        //使用原生方法进行queryString进行查询
        QueryBuilder queryBuilder=new QueryStringQueryBuilder("我修改了内容")
                .defaultField("content");
        NativeSearchQuery build = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withPageable(PageRequest.of(0, 2))
                .build();
        List<Hello> hellos = template.queryForList(build, Hello.class);
        hellos.stream().forEach(System.out::println);
    }


自定义查询方法命名规则
关键字命名规则解释示例
andfindByField1AndField2根据Field1和Field2获得数据findByTitleAndContent
orfindByField1OrField2根据Field1或Field2获得数据findByTitleOrContent
isfindByField根据Field获得数据findByTitle
notfindByFieldNot根据Field获得补集数据findByTitleNot
betweenfindByFieldBetween获得指定范围的数据findByPriceBetween
lessThanEqualfindByFieldLessThan获得小于等于指定值的数据findByPriceLessThan
拆词实现字段or查询、

注意:拆词查询后搜索词之间是and关系,一般应该为or来进行查询。
实现:使用原生的查询一个
步骤:
1.创建NativeSearchQuery对象
QueryBuilder来构造条件
2.使用ES的模板对象来执行查询
3.获取查询结果

@Test
    public void findByContentOr() {
        //使用原生方法进行queryString进行查询
        //构造查询条件
        QueryBuilder queryBuilder=new QueryStringQueryBuilder("我修改了内容")
                .defaultField("content");
        //生成模板需要的对象以及设置分页信息
        NativeSearchQuery build = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withPageable(PageRequest.of(0, 2))
                .build();
        //使用模板执行查询
        List<Hello> hellos = template.queryForList(build, Hello.class);
        hellos.stream().forEach(System.out::println);
    }

SpringData是一个用于简化数据库访问,并支持云服务的开源框架

配置

pojo中已经指定了索引和type名

操作

@ID
_id的生成配置地方寻找???

查询时候term和querystring怎么区别?

此处的查询是分词后每个词是and关系即都需要满足,如果想要实现or的操作需要使用原生的查询

编写pojo

在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值