003 SpringBoot操作ElasticSearch7.x

文章目录

    • 5.SpringBoot集成ElasticSearch7.x
      • 1.添加依赖
      • 2.yml配置
      • 3.创建文档对象
      • 4.继承ElasticsearchRepository
      • 5.注入ElasticsearchRestTemplate
    • 6.SpringBoot操作ElasticSearch
      • 1.ElasticsearchRestTemplate索引操作
      • 2.ElasticsearchRepository文档操作
      • 3.ElasticsearchRestTemplate文档操作
      • 4.ElasticsearchRestTemplate数据检索
    • 完整测试代码

5.SpringBoot集成ElasticSearch7.x

1.添加依赖

本文使用springboot版本为2.7

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>

spring官网es对应版本关系 https://docs.spring.io/spring-data/elasticsearch/reference/elasticsearch/versions.html

2.yml配置

spring:
  data:
    elasticsearch:
      repositories:
        enabled: true  #打开elasticsearch仓库,默认true
  elasticsearch:
    #username:
    #password:
    #path-prefix:
    uris: http://127.0.0.1:9200
    connection-timeout: 60000   #连接elasticsearch超时时间
    socket-timeout: 30000

3.创建文档对象

/**
 * @author moshangshang
 * createIndex默认为true自动创建索引
 */
@Data
@AllArgsConstructor
@Document(indexName ="books",createIndex = true)
public class Books implements Serializable {

    @Id
    private Integer id;

    //指定字段类型和分词器
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String name;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String describe;

}
public enum FieldType {
	Text,
	Integer,
	Long,
	Date,
	Float,
	Double,
	Boolean,
	Object,
	Auto,
	Nested,
	Ip,
	Attachment,
	Keyword
}
@GeoPointField  //地理位置类型字段
private GeoPoint location;
@Field(index = false) //不进行索引

4.继承ElasticsearchRepository

/**
 * @author moshangshang
 */
public interface BookMapper extends ElasticsearchRepository<Books,String> {
}

自定义接口查询方法

 List<Book> findByNameAndPrice(String name, Integer price);

等同于

{
    "query": {
        "bool" : {
            "must" : [
                { "query_string" : { "query" : "?", "fields" : [ "name" ] } },
                { "query_string" : { "query" : "?", "fields" : [ "price" ] } }
            ]
        }
    }
}

详细接口方法命名见官方文档:

https://docs.spring.io/spring-data/elasticsearch/reference/elasticsearch/repositories/elasticsearch-repository-queries.html

5.注入ElasticsearchRestTemplate

   @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

建议通过elasticsearchRestTemplate进行es操作,ElasticsearchRepository也可直接操作,但多数方法已过时,不建议用

6.SpringBoot操作ElasticSearch

1.ElasticsearchRestTemplate索引操作

   /**
     * 操作文档索引
     * 如果文档的createIndex设置为true自动创建,则可以直接创建映射会自动创建索引
     * 如果为false,直接创建映射会返回Document的json,但索引并未创建
     */
    @GetMapping("/create/index")
    public Document createIndex(){
        // 获取操作的索引文档对象
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Books.class);
        //判断索引是否存在
        log.info("exists:{}",indexOperations.exists());
        //删除索引文档
        log.info("delete:{}",indexOperations.delete());
        //创建索引,如果存在则会抛异常
        log.info("create:{}",indexOperations.create());
        //创建映射,返回Document
        log.info("createMapping:{}",indexOperations.createMapping());
        indexOperations.delete();
        //创建索引同时创建映射,如果存在索引则会抛异常
        log.info("createWithMapping{}",indexOperations.createWithMapping());
        //更新映射mapping
        log.info("putMapping:{}",indexOperations.putMapping());
        // 配置映射
        return indexOperations.createMapping();
    }

2.ElasticsearchRepository文档操作

 /**
     * 发送保存数据,会自动创建索引文档并保存数据
     * 如果文档的createIndex设置为false,该方法会创建索引
     */
    @GetMapping("/data/{id}")
    public String data(@PathVariable Integer id){
        //新增数据,等同于PUT/POST方式发送数据
        bookMapper.save(new Books(id,"四大名著西游记111","著名的神话小说"));
        //查所有数据
        bookMapper.findAll().forEach(System.out::println);
        bookMapper.findAllById(Arrays.asList("1", "10")).forEach(System.out::println);
        bookMapper.findById(id.toString()).ifPresent(System.out::println);
        //查所有数据按id排序
        bookMapper.findAll(Sort.by("id")).forEach(System.out::println);
        //删除指定id数据
        bookMapper.deleteById(String.valueOf(id));

        //分页查询
        Page<Books> booksPage = bookMapper.findAll(Pageable.ofSize(2));
        //效果等同于booksPage2.getContent().forEach()
        log.info("总页数:{}",booksPage.getTotalPages());
        System.out.println("第1页");
        booksPage.forEach(System.out::println);
        int i = 1;
        //判断是否有下一页,hasPrevious方法判断是否有前一页
        while (booksPage.hasNext()){
            i++;
            booksPage = bookMapper.findAll(booksPage.nextPageable());
            log.info("第{}页",i);
            booksPage.forEach(System.out::println);
        }

        return "success";
    }

3.ElasticsearchRestTemplate文档操作

注意:直接执行可能会删除时更新操作还未执行完,全部删除时会导致更新的数据还在

    @GetMapping("/data1/{id}")
    public UpdateResponse data1(@PathVariable Integer id){
        //添加 
        elasticsearchRestTemplate.save(new Books(id,"四大名著西游记111","著名的神话小说"));
        elasticsearchRestTemplate.save(
                new Books(1,"四大名著西游记111","著名的神话小说"),
                new Books(2,"四大名著西游记111","著名的神话小说"),
                new Books(3,"四大名著西游记111","著名的神话小说"));
        /**
         * 修改 跟新增是相同。若id已存在,覆盖其他所有字段,
         * 若某个字段没有值,则为null。无法修改单个字段
         */
        elasticsearchRestTemplate.save(new Books(3,"四大名著西游记222",null));

        //修改部分字段
        Document document = Document.create();
        document.put("name", "三国演义");
        document.put("describe", "著名的小说");
        //需要修改的id和参数
        UpdateQuery updateQuery = UpdateQuery.builder(String.valueOf(id))
                .withDocument(document).build();
        UpdateResponse response = elasticsearchRestTemplate.update(updateQuery, IndexCoordinates.of("books"));

        //批量修改部分字段
        List<UpdateQuery> updateQueryList = new ArrayList<>();
        for (int i = 1; i <= 3; i++) {
            Document bulkDocument = Document.create();
            bulkDocument.put("name", "三国演义"+i);
            bulkDocument.put("describe", "著名的小说"+i);
            //索引i数据不存在会报错
            UpdateQuery updateQueryBulk = UpdateQuery.builder(Long.toString(i))
                    .withDocument(bulkDocument).build();
            updateQueryList.add(updateQueryBulk);
        }
        elasticsearchRestTemplate.bulkUpdate(updateQueryList, IndexCoordinates.of("books"));

        //查询
        Books books = elasticsearchRestTemplate.get(id.toString(), Books.class, IndexCoordinates.of("books"));
        log.info("查询数据:{}",books);
        //删除
        String delete = elasticsearchRestTemplate.delete(id.toString(), Books.class);
        log.info("删除数据id:{}",delete);
        //条件删除
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery("name", "三国"))
                .build();
        ByQueryResponse queryResponse = elasticsearchRestTemplate.delete(nativeSearchQuery, Books.class, IndexCoordinates.of("books"));
        log.info("删除queryResponse数据数量:{}",queryResponse.getDeleted());
        
        //全部删除
        //直接执行可能会删除时更新操作还未执行完,全部删除时会导致更新的数据还在
        ByQueryResponse queryResponse1 = elasticsearchRestTemplate.delete(
                new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).build(),
                Books.class, IndexCoordinates.of("books"));
        log.info("删除queryResponse1数据数量:{}",queryResponse1.getDeleted());
        return response;
    }

4.ElasticsearchRestTemplate数据检索

基础高亮查询

   @GetMapping("/query")
    public void query() {
        // 构建查询条件(NativeSearchQueryBuilder更接近原生查询)
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        //查询
        queryBuilder.withQuery(QueryBuilders.matchQuery("username","lisi")).withSort(Sort.by("age").ascending());
        //高亮查询
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("username");
        //多个匹配项高亮关闭
        highlightBuilder.requireFieldMatch(false);
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        //设置高亮
        queryBuilder.withHighlightBuilder(highlightBuilder);

        SearchHits<News> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), News.class);

        searchHits.forEach(e -> {
            log.info("全文检索{}", e.getContent());
            Map<String, List<String>> highlightFields = e.getHighlightFields();
            List<String> list = highlightFields.get("username");
            if (list != null) {
                list.forEach(ex -> log.info("高亮{}", ex));
            }
        });

    }

NativeSearchQueryBuilder条件构建

 
        // 构建查询条件(NativeSearchQueryBuilder更接近原生查询)
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();  
        //查询全部 match_all
        queryBuilder.withQuery(QueryBuilders.matchAllQuery());  
        //查询全部 过滤时间范围
        queryBuilder.withQuery(QueryBuilders.matchAllQuery())
                .withFilter(QueryBuilders.rangeQuery("time")
                        .timeZone("+08:00")
                        .format("yyyy-MM-dd HH:mm:ss")
                        .gt("2024-06-27 14:22:22")
                        .lt("2024-06-27 14:22:28"));
        //查询全部 match_all 并按age升序
        queryBuilder.withQuery(QueryBuilders.matchAllQuery()).withSort(Sort.by("age").ascending());
        //查询全部 match_all 并按age升序 并分页
        queryBuilder.withQuery(QueryBuilders.matchAllQuery()).withSort(Sort.by("age").ascending()).withPageable(PageRequest.of(2, 10));

        //term精确查询,整体匹配
        // 查询内容只是为数字时 推荐使用term 进行检索,但是当使用term中进行文本内容的全量检索时term不会检索任何内容
        queryBuilder.withQuery(QueryBuilders.termQuery("age", "2"));
        //多匹配值查询
        queryBuilder.withQuery(QueryBuilders.termsQuery("age", "2", "3"));

        //全文检索 match_query
        queryBuilder.withQuery(QueryBuilders.matchQuery("address", "Beijing"));
        //or 只要有一个词存在则就符合条件,and表示每个词都需存在
        queryBuilder.withQuery(QueryBuilders.matchQuery("address", "Beijing shanghai").operator((Operator.OR)));

        //短语匹配 match_phrase
        queryBuilder.withQuery(QueryBuilders.matchPhraseQuery("address", "Beijing aaa"));
        //短语匹配 match_phrase_prefix 它允许文本中最后一项使用前缀匹配
        queryBuilder.withQuery(QueryBuilders.matchPhrasePrefixQuery("address", "Beijing a"));

        //多字段匹配 multi_match
        queryBuilder.withQuery(QueryBuilders.multiMatchQuery("Beijing aaa", "address", "username"));
        queryBuilder.withQuery(QueryBuilders.multiMatchQuery("Beijing aaa", "address", "username")
                //提升该字段查询匹配权重
                .field("address", 10));

        //match_bool_prefix 允许文本中最后一项使用前缀匹配 其它都是term query。
        queryBuilder.withQuery(QueryBuilders.matchBoolPrefixQuery("address", "b"));

        //id查询
        queryBuilder.withQuery(QueryBuilders.idsQuery().addIds("1", "2"));

        //区间查询
        queryBuilder.withQuery(QueryBuilders.rangeQuery("age").gte(2).lte(3));


        //bool复合查询
        //must必须  mustNot必须不
        //should 条件可以满足也可以不满足,在查询中如果有满足should的条件就会增加相关性得分
        QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("address", "Beijing"))
                .must(QueryBuilders.matchQuery("username", "lisi"))
                .mustNot(QueryBuilders.matchQuery("age", "1"))
                .should(QueryBuilders.matchQuery("age", "2"))
                //minimumShouldMatch 最小匹配度,必须 匹配的should子句的数量或百分比。
                .minimumShouldMatch("50%");

        //filter结果过滤
        QueryBuilders.boolQuery()
                .filter(QueryBuilders.rangeQuery("age").gte(1).lte(2));
        //与上面结果相等
        QueryBuilders.boolQuery()
                .must(QueryBuilders.rangeQuery("age").gte(1).lte(2));

完整测试代码

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>test</name>


    <properties>
        <java.version>8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

/**
 * @author moshangshang
 */
@Data
@AllArgsConstructor
@Document(indexName ="news")
public class News implements Serializable {

    @Id
    private Integer id;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String address;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String username;

    @Field(type = FieldType.Long)
    private Integer age;
}


/**
 * @author moshangshang
 */
@Data
@AllArgsConstructor
@Document(indexName ="books")
public class Books implements Serializable {

    @Id
    private Integer id;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String name;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String describe;

}

/**
 * @author moshangshang
 */
public interface BookMapper extends ElasticsearchRepository<Books,String> {
}
/**
 * @author moshangshang
 */
@Slf4j
@RestController
@RequestMapping("/es")
public class BookController {

    @Autowired
    private BookMapper bookMapper;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;


    /**
     * 操作文档索引
     * 如果文档的createIndex设置为true自动创建,则可以直接创建映射会自动创建索引
     * 如果为false,直接创建映射会返回Document的json,但索引并未创建
     */
    @GetMapping("/create/index")
    public Document createIndex() {
        // 获取操作的索引文档对象
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Books.class);
        //判断索引是否存在
        log.info("exists:{}", indexOperations.exists());
        //删除索引文档
        log.info("delete:{}", indexOperations.delete());
        //创建索引,如果存在则会抛异常
        log.info("create:{}", indexOperations.create());
        //创建映射,返回Document
        log.info("createMapping:{}", indexOperations.createMapping());
        indexOperations.delete();
        //创建索引同时创建映射,如果存在索引则会抛异常
        log.info("createWithMapping{}", indexOperations.createWithMapping());
        //更新映射mapping
        log.info("putMapping:{}", indexOperations.putMapping());
        // 配置映射
        return indexOperations.createMapping();
    }


    /**
     * 发送保存数据,会自动创建索引文档并保存数据
     * 如果文档的createIndex设置为false,该方法会创建索引
     */
    @GetMapping("/data/{id}")
    public String data(@PathVariable Integer id) {
        //新增数据
        bookMapper.save(new Books(id, "四大名著西游记111", "著名的神话小说"));
        //查所有数据
        bookMapper.findAll().forEach(System.out::println);
        bookMapper.findAllById(Arrays.asList("1", "10")).forEach(System.out::println);
        bookMapper.findById(id.toString()).ifPresent(System.out::println);
        //查所有数据按id排序
        bookMapper.findAll(Sort.by("id")).forEach(System.out::println);
        //删除指定id数据
        //bookMapper.deleteById(String.valueOf(id));
        //删除匹配的数据
        bookMapper.delete(new Books(null, "四大名著西游记111", "著名的神话小说"));
        //删除所有数据
        //bookMapper.deleteAll();

        //分页查询
        Page<Books> booksPage = bookMapper.findAll(Pageable.ofSize(2));
        //效果等同于booksPage2.getContent().forEach()
        log.info("总页数:{}", booksPage.getTotalPages());
        System.out.println("第1页");
        booksPage.forEach(System.out::println);
        int i = 1;
        //判断是否有下一页,hasPrevious方法判断是否有前一页
        while (booksPage.hasNext()) {
            i++;
            booksPage = bookMapper.findAll(booksPage.nextPageable());
            log.info("第{}页", i);
            booksPage.forEach(System.out::println);
        }

        return "success";
    }


    @GetMapping("/data1/{id}")
    public UpdateResponse data1(@PathVariable Integer id) {
        //添加
        elasticsearchRestTemplate.save(new Books(id, "四大名著西游记111", "著名的神话小说"));
        elasticsearchRestTemplate.save(
                new Books(1, "四大名著西游记111", "著名的神话小说"),
                new Books(2, "四大名著西游记111", "著名的神话小说"),
                new Books(3, "四大名著西游记111", "著名的神话小说"));
        /**
         * 修改 跟新增是相同。若id已存在,覆盖其他所有字段,
         * 若某个字段没有值,则为null。无法修改单个字段
         */
        elasticsearchRestTemplate.save(new Books(3, "四大名著西游记222", null));

        //修改部分字段
        Document document = Document.create();
        document.put("name", "三国演义");
        document.put("describe", "著名的小说");
        //需要修改的id和参数
        UpdateQuery updateQuery = UpdateQuery.builder(String.valueOf(id))
                .withDocument(document).build();
        UpdateResponse response = elasticsearchRestTemplate.update(updateQuery, IndexCoordinates.of("books"));

        //批量修改部分字段
        List<UpdateQuery> updateQueryList = new ArrayList<>();
        for (int i = 1; i <= 3; i++) {
            Document bulkDocument = Document.create();
            bulkDocument.put("name", "三国演义" + i);
            bulkDocument.put("describe", "著名的小说" + i);
            //索引i数据不存在会报错
            UpdateQuery updateQueryBulk = UpdateQuery.builder(Long.toString(i))
                    .withDocument(bulkDocument).build();
            updateQueryList.add(updateQueryBulk);
        }
        elasticsearchRestTemplate.bulkUpdate(updateQueryList, IndexCoordinates.of("books"));

        //查询
        Books books = elasticsearchRestTemplate.get(id.toString(), Books.class, IndexCoordinates.of("books"));
        log.info("查询数据:{}", books);
        //删除
        String delete = elasticsearchRestTemplate.delete(id.toString(), Books.class);
        log.info("删除数据id:{}", delete);
        //条件删除
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery("name", "三国"))
                .build();
        ByQueryResponse queryResponse = elasticsearchRestTemplate.delete(nativeSearchQuery, Books.class, IndexCoordinates.of("books"));
        log.info("删除queryResponse数据数量:{}", queryResponse.getDeleted());
        //全部删除
        //直接执行可能会删除时更新操作还未执行完,全部删除时会导致更新的数据还在
        ByQueryResponse queryResponse1 = elasticsearchRestTemplate.delete(
                new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).build(),
                Books.class, IndexCoordinates.of("books"));
        log.info("删除queryResponse1数据数量:{}", queryResponse1.getDeleted());
        return response;
    }


  
    @GetMapping("/query")
    public void query() {
        // 构建查询条件(NativeSearchQueryBuilder更接近原生查询)
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        //查询全部 match_all
        queryBuilder.withQuery(QueryBuilders.matchAllQuery());
        //查询全部 过滤时间范围
        queryBuilder.withQuery(QueryBuilders.matchAllQuery())
                .withFilter(QueryBuilders.rangeQuery("time")
                        .timeZone("+08:00")
                        .format("yyyy-MM-dd HH:mm:ss")
                        .gt("2024-06-27 14:22:22")
                        .lt("2024-06-27 14:22:28"));
        //查询全部 match_all 并按age升序
        queryBuilder.withQuery(QueryBuilders.matchAllQuery()).withSort(Sort.by("age").ascending());
        //查询全部 match_all 并按age升序 并分页
        queryBuilder.withQuery(QueryBuilders.matchAllQuery()).withSort(Sort.by("age").ascending()).withPageable(PageRequest.of(2, 10));

        //term精确查询,整体匹配
        // 查询内容只是为数字时 推荐使用term 进行检索,但是当使用term中进行文本内容的全量检索时term不会检索任何内容
        queryBuilder.withQuery(QueryBuilders.termQuery("age", "2"));
        //多匹配值查询
        queryBuilder.withQuery(QueryBuilders.termsQuery("age", "2", "3"));

        //全文检索 match_query
        queryBuilder.withQuery(QueryBuilders.matchQuery("address", "Beijing"));
        //or 只要有一个词存在则就符合条件,and表示每个词都需存在
        queryBuilder.withQuery(QueryBuilders.matchQuery("address", "Beijing shanghai").operator((Operator.OR)));

        //短语匹配 match_phrase
        queryBuilder.withQuery(QueryBuilders.matchPhraseQuery("address", "Beijing aaa"));
        //短语匹配 match_phrase_prefix 它允许文本中最后一项使用前缀匹配
        queryBuilder.withQuery(QueryBuilders.matchPhrasePrefixQuery("address", "Beijing a"));

        //多字段匹配 multi_match
        queryBuilder.withQuery(QueryBuilders.multiMatchQuery("Beijing aaa", "address", "username"));
        queryBuilder.withQuery(QueryBuilders.multiMatchQuery("Beijing aaa", "address", "username")
                //提升该字段查询匹配权重
                .field("address", 10));

        //match_bool_prefix 允许文本中最后一项使用前缀匹配 其它都是term query。
        queryBuilder.withQuery(QueryBuilders.matchBoolPrefixQuery("address", "b"));

        //id查询
        queryBuilder.withQuery(QueryBuilders.idsQuery().addIds("1", "2"));

        //区间查询
        queryBuilder.withQuery(QueryBuilders.rangeQuery("age").gte(2).lte(3));


        //bool复合查询
        //must必须  mustNot必须不
        //should 条件可以满足也可以不满足,在查询中如果有满足should的条件就会增加相关性得分
        QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("address", "Beijing"))
                .must(QueryBuilders.matchQuery("username", "lisi"))
                .mustNot(QueryBuilders.matchQuery("age", "1"))
                .should(QueryBuilders.matchQuery("age", "2"))
                //minimumShouldMatch 最小匹配度,必须 匹配的should子句的数量或百分比。
                .minimumShouldMatch("50%");

        //filter结果过滤
        QueryBuilders.boolQuery()
                .filter(QueryBuilders.rangeQuery("age").gte(1).lte(2));
        //与上面结果相等
        QueryBuilders.boolQuery()
                .must(QueryBuilders.rangeQuery("age").gte(1).lte(2));
        //查询
        queryBuilder.withQuery(QueryBuilders.matchQuery("username","lisi")).withSort(Sort.by("age").ascending());
        //高亮查询
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("username");
        //多个匹配项高亮关闭
        highlightBuilder.requireFieldMatch(false);
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        //设置高亮
        queryBuilder.withHighlightBuilder(highlightBuilder);

        SearchHits<News> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), News.class);

        searchHits.forEach(e -> {
            log.info("全文检索{}", e.getContent());
            Map<String, List<String>> highlightFields = e.getHighlightFields();
            List<String> list = highlightFields.get("username");
            if (list != null) {
                list.forEach(ex -> log.info("高亮{}", ex));
            }
        });

    }


}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/750016.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微服务应用与开发知识点练习【Gateway,OpenFeign,Dubbo,RocketMQ和RabbitMQ,JPA,Redis,Mycat】

一、选择题 【Gateway】 1.Spring Cloud Gateway与Nacos整合实现负载均衡时&#xff0c;路由配置中的URI前缀应该是&#xff1f;&#xff08;A &#xff09; A. lb:// B. nacos:// C. http:// D. discovery:// Spring Cloud Gateway与Nacos整合实现负载均衡时&#xff0c…

js删除el-table删除新增项,有的已经保存有的未经保存

有时候在弹窗中的弹窗要删除数据,有的是刚新增进来的,没有经过保存就没有id,有的已经保存过就有id 根据情况设定是否为编辑模式,如果为编辑模式就需要进行筛选删除及接口,如果不是编辑模式,只需要进行筛选删除 this.editFlag true; // 为编辑模式// 删除伤亡名单handelDel() …

酷睿Ultra 200V系CPU全阵容规格、跑分出炉:拉了坨大的

从最近几个月 12 代酷睿 CPU 大面积降价清库存&#xff0c;到 13、14 代高端 U 大范围翻车问题迟迟得不到解决。 这就很难不让人生出一种 Intel 似乎真无暇顾及老款 U&#xff0c;而是将有限精力通通放在了接下来酷睿 Ultra 处理器上的感觉。 当然&#xff0c;作为新工艺、新架…

【Java面试场景题】如何优化系统架构设计来缓解流量压力提升并发性能?

一、问题解析 我会以直播互动为例&#xff0c;带你看看读多写多的情况下如何应对流量压力。- 一般来说&#xff0c;这种服务多数属于实时互动服务&#xff0c;因为时效性要求很高&#xff0c;导致很多场景下&#xff0c;我们无法用读缓存的方式来降低核心数据的压力。所以&…

AR导航技术加持,图书馆阅读体验智慧升级

在信息爆炸的今天&#xff0c;图书馆作为知识的宝库&#xff0c;其藏书量和种类日益增多。然而&#xff0c;传统的图书馆导航方式已逐渐无法满足用户对快速、准确定位图书的需求。本文将探讨图书馆AR地图导航的实现原理、技术优势、功能特点以及市场前景&#xff0c;揭示为何AR…

【深度学习】Error: TensorBoard could not bind to port 6006 问题解决

问题描述 在启动TensorBoard时&#xff0c;遇到了端口冲突&#xff0c;如下图所示&#xff1a; 根据提示&#xff0c;出错原因是因为端口已经被占用了&#xff0c;因此我们要结束占用这个端口的进程。 我的系统是Windows系统&#xff0c;并不是Linux&#xff0c;网上大部分方…

vue 组件下 img 标签动态传入不展示

效果 解决办法&#xff1a; require() <titleComponent:title"业务工作概览":src"require(/assets/imgs/evaluation/overviewStatistics.png)"></titleComponent> 效果&#xff1a;

Nuxt3 的生命周期和钩子函数(三)

title: Nuxt3 的生命周期和钩子函数&#xff08;三&#xff09; date: 2024/6/27 updated: 2024/6/27 author: cmdragon excerpt: 摘要&#xff1a;概述了Nuxt3的关键生命周期钩子用途&#xff0c;如page:finish用于页面加载后处理&#xff0c;page:transition:finish处理过…

C++之STL(六七)

1、变动性算法 #include <vector> #include <iostream> #include <list> #include <algorithm>using namespace std;void print_element(int n) {cout << n << ; }void add_3(int& n) {n n 3; }int fun(int n) {return 2 * n; }boo…

【HarmonyOS】模拟器一直停留在开机页面,无法进入手机桌面

环境:window 10, 开发者工具:DevEco Studio NEXT Developer Beta1 Build #DS-233.14475.28.36.503402 Build Version: 5.0.3.402, built on June 16, 2024 Runtime version: 17.0.101-b1087.17 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 10.0 GC: G1 Y…

【Dison夏令营 Day 01】如何用Python写一个游戏“石头剪刀布”

欢迎你们踏入这个充满无限可能性的编程世界&#xff01;作为一名热爱Python的开发者&#xff0c;我深感编程的魅力&#xff0c;并希望与你们一同分享这份乐趣和激情。编程&#xff0c;不仅仅是一种技能&#xff0c;更是一种思维方式和解决问题的工具。在Python的世界里&#xf…

Linux内核中网络数据的流量控制(TC: Traffic control 和 QDISC)

(个人能力有限&#xff0c;本文如有错误之处&#xff0c;欢迎交流指正) 1 简介 在进行网络数据 接收 和 发送 过程中&#xff0c;网卡设备到L3(网络层) 中间会经历流量控制(Traffic control)。 《BPF之巅.洞悉Linux系统和应⽤性能》P413 qdisc这个可选层可以⽤来管理⽹络包的…

【博士每天一篇文献-综述】Biological underpinnings for lifelong learning machines

阅读时间&#xff1a;2023-12-17 1 介绍 年份&#xff1a;2015 作者&#xff1a;Dhireesha Kudithipudi&#xff0c;Mario Aguilar-Simon&#xff0c;其中通讯作者Josh Bongard教授也是另一篇论文的通讯作者《Neural modularity helps organisms evolve to learn new skills …

智慧校园-缴费管理系统总体概述

在构建现代化教育环境的过程中&#xff0c;智慧校园缴费管理系统脱颖而出&#xff0c;成为提升校园财务管理效率与服务质量的关键一环。缴费管理系统需要精心设计&#xff0c;通过科技力量&#xff0c;让原本繁琐的缴费流程变得简单快捷&#xff0c;同时增强家校之间的互动与信…

通过代理从ARDUINO IDE直接下载开发板包

使用免费代理 实现ARDUINO IDE2.3.2 下载ESP8266/ESP32包 免费代理 列表 测试代理是否可用的 网站 有时&#xff0c;代理是可用的&#xff0c;但依然有可能找不到开发板管理器的资料包。 可以多换几个代理试试。 代理的配置 文件 -> 首选项 -> 网络 进入后做如下配置…

linux 安装腾讯会议和解决ubuntu打开腾讯会议提示:不兼容 wayland 协议

一. 下载腾讯会议安装包 腾讯会议下载链接 二. 命令行安装 cd [安装包路径] sudo dpkg -i TencentMeeting_0300000000_3.19.1.400_x86_64_default.publish.deb 三. 打开腾讯会议提示无法支持wayland 协议 解决方法: 打开终端 sudo vi /etc/gdm3/custom.conf打开 #Wayland…

Zabbix 监控系统部署

Zabbix 监控系统部署 Zabbix是一个企业级开源分布式监控解决方案&#xff0c;可监控网络的众多参数以及服务器、虚拟机、应用程序、服务、数据库、网站、云等的运行状况和完整性。 Zabbix 使用灵活的通知机制&#xff0c;允许用户为几乎任何事件配置基于电子邮件的警报。这允许…

Linux-笔记 嵌入式gdb远程调试

目录 前言 实现 1、内核配置 2、GDB移植 3、准备调试程序 4、开始调试 前言 gdb调试器是基于命令行的GNU项目调试器&#xff0c;通过gdb工具我们可以实现许多调试手段&#xff0c;同时gdb支持多种语言&#xff0c;兼容性很强。 在桌面 Linux 系统&#xff08;如 Ubuntu、Cent…

从新手到高手:彻底掌握MySQL表死锁

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 从新手到高手&#xff1a;彻底掌握MySQL表死锁 前言什么是死锁mysql死锁的原因1. 互斥资源的竞争…

加速鸿蒙生态共建,蚂蚁mPaaS助力鸿蒙原生应用开发创新

6月21日-23日&#xff0c;2024华为开发者大会&#xff08;HDC 2024&#xff09;如期举行。在22日的【鸿蒙生态伙伴SDK】分论坛中&#xff0c;正式发布了【鸿蒙生态伙伴SDK市场】&#xff0c;其中蚂蚁数科旗下移动开发平台mPaaS&#xff08;以下简称&#xff1a;蚂蚁mPaaS&#…