003 SpringBoot操作ElasticSearch7.x

news2024/11/23 23:26:29

文章目录

    • 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));
            }
        });

    }


}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mybatis 系列全解(3)——全网免费最细最全,手把手教,学完就可做项目!

Mybatis 系列全解&#xff08;3&#xff09; 1. 多对一处理2. 一对多处理3. 动态SQL3.1 什么是动态SQL3.2 搭建环境3.3 IF3.4 Choose(when,otherwise)3.5 Set3.6 SQL片段3.7 Foreach 4. 缓存4.1 简介4.2 Mybatis 缓存4.3 一级缓存4.4 二级缓存4.5 缓存原理 1. 多对一处理 1&am…

携程任我行有什么用?

眼看一直到十月份都没啥假期了 五一出去玩买了几张携程的卡&#xff0c;想着买景点门票、酒店啥的能有优惠&#xff0c;但最后卡里的钱没用完不说&#xff0c;还有几张压根就没用出去 但是我又不想把卡一直闲置在手里&#xff0c;就怕过期了 最后在收卡云上99.1折出掉了&…

vue3中的图片懒加载指令及全局注册

vue3中的图片懒加载指令及全局注册 最近重新刷了一遍黑马的小兔鲜前端项目&#xff0c;发现有个懒加载的指令之前还没有用过。而且写法相对固定&#xff0c;因此记录一下 首先&#xff0c;懒加载&#xff08;Lazy Loading&#xff09;的作用是延迟加载某些资源或组件&#xf…

Python生成图形验证码

文章目录 安装pillow基本用法生成代码 安装pillow pip install pillow 基本用法 特殊字体文字 如下所示&#xff0c;将下载下来的ttf字体文件放到py文件同一文件夹下 分享一个免费下载字体网站&#xff1a;http://www.webpagepublicity.com/free-fonts.html 我选的字体是Baj…

专题页面设计指南:从构思到实现

如何设计专题页&#xff1f;你有什么想法&#xff1f;专题页的设计主要以发扬产品优势为核心。一个好的专题页可以从不同的角度向用户介绍产品&#xff0c;扩大产品的相关优势&#xff0c;表达产品的优势&#xff0c;让用户在短时间内了解产品。因此&#xff0c;在设计详细信息…

纯css写一个动态圣诞老人

效果预览 在这篇文章中&#xff0c;我们将学习如何使用CSS来创建一个生动的圣诞老人动画。通过CSS的魔力&#xff0c;我们可以让圣诞老人在网页上摇摆&#xff0c;仿佛在向我们招手庆祝圣诞节和新年。 实现思路 实现这个效果的关键在于CSS的keyframes动画规则以及各种CSS属性…

Python 基础:用 json 模块存储和读取数据

目录 一、用 json 存储数据二、用 json 读取数据 遇到看不明白的地方&#xff0c;欢迎在评论中留言呐&#xff0c;一起讨论&#xff0c;一起进步&#xff01; 本文参考&#xff1a;《Python编程&#xff1a;从入门到实践&#xff08;第2版&#xff09;》 用户关闭程序时&#…

step6:改用单例模式

文章目录 文章介绍codemain.cppSerialPort.qmlSerialPortHandler.h 文章介绍 案例MF改为单例模式 参考之前写过的关于单例模式的文章单例模式1、单例模式2 code main.cpp qmlRegisterSingletonType(“com.example.serialport”, 1, 0, “SerialPortHandler”, SerialPortHan…

【Python】易错题 [1]

目录 一、选择&#xff1a; 1.列表的复制​编辑 2.函数 二、填空 一、选择&#xff1a; 1.列表的复制 在Python中&#xff0c;列表是可变的数据类型。当将一个列表赋值给另一个变量时&#xff0c;实际上是将这个变量的引用指向原始列表。&#xff08;指针&#xff09;因此&…

软件系统测试包括哪些测试内容?有什么作用?

在软件开发的过程中&#xff0c;软件系统测试是不可或缺的环节。它是为了验证并评估软件系统的功能、性能以及其它需要满足的特性。那么&#xff0c;软件系统测试包括哪些测试呢?又有什么作用? 软件系统测试是通过执行一系列策略和技术&#xff0c;检测软件系统是否满足用户…

docker 部署jitsi meet

1. 部署环境&#xff1a; 1.1 vm 虚拟机 安装的 centos 7 1.2 centos7安装docker 和 docker-compose 2.docker命令 官网部署文档地址&#xff1a;&#xff08;文档地址有可能失效&#xff09; Self-Hosting Guide - Docker | Jitsi Meet 2.1Download and extract the late…

AL8807是一款降压型DC/DC转换器,旨在以恒定电流驱动LED,可串联驱动多达9个LED,从6V至36V的电压源

一般描述 AL8807是一款降压型DC/DC转换器&#xff0c;旨在以恒定电流驱动LED。根据LED的正向电压&#xff0c;该设备可串联驱动多达9个LED&#xff0c;从6V至36V的电压源。LED的串联连接提供相同的LED电流&#xff0c;从而实现均匀的亮度&#xff0c;并消除了对镇流电阻…

4大wordpress渐变色网站模板

家居摆件wordpress外贸模板 家居装饰、配件、摆件wordpress外贸模板&#xff0c;适合搞家居装饰的公司官网使用。 https://www.jianzhanpress.com/?p3515 玩具wordpress外贸模板 简洁玩具wordpress外贸模板&#xff0c;适合做跨境电商外贸公司使用的wordpres外贸s网站主题。…

Android U Settings 应用中 APN 菜单实现的代码逻辑

功能简介 MobileNetwork移动网络设置页面下有【接入点设置】(APN)。 问题:为什么Controller初始化找不到pref,然后报错。 Note:什么时候切换成Controller的呢?在Android T&U 上还没有更新成kt实现 ,但是已经有Controller的方案。 流程逻辑 1、界面“telephony_a…

frida的安装使用以及解决抓包app时遇到的证书校验

frida的安装和使用 这里使用夜神模拟器来演示frida的使用&#xff0c;因为真机开启frida-server服务时需要root权限,模拟器自带root 下载夜神模拟器并启动 夜神官网 打开power shell&#xff0c; adb连接模拟器&#xff0c;查看模拟器的系统型号 adb connect 127.0.0.1:6200…

MySQL学习(3):SQL语句之数据定义语言:DDL

1.SQL通用语法与分类 &#xff08;1&#xff09;通用语法 &#xff08;2&#xff09;分类 2.DDL 2.1数据库操作 show DATABASES; #查询所有数据库select DATABASE(); #查询当前数据库create DATABASE 数据库名称 [default charest 字符集] [collate 排列规则]; #default cha…

VC++学习(6)——菜单编程,消息捕获机制和顺序;创建标记、缺省、图形、不可用等菜单;命令更新模式;右键的弹出菜单

目录 引出第6讲 菜单编程在CMainFrame中捕获消息响应捕获顺序插曲&#xff1a;删除函数的方法 消息分类菜单的结构创建标记菜单创建缺省菜单创建图形菜单菜单项不允许使用如何整个菜单取消命令更新模式右键弹出菜单功能添加方式显示位置定义事件 动态添加定义响应 总结第五讲 文…

DELL:利用大语言模型(LLM)生成评论与解释,革新虚假信息检测

ACL 2024 DELL: Generating Reactions and Explanations for LLM-Based Misinformation Detection https://arxiv.org/abs/2402.10426https://arxiv.org/abs/2402.10426 1.概述 大型语言模型(LLM)虽在诸多领域显示出色性能,但在直接应用于新闻真实性鉴别时,面临两大核心挑…

【React】变量 useState

开发需要&#xff0c;随便学学react。上手第一天&#xff0c;感觉这个JS语法很怪&#xff0c;没有什么逻辑性&#xff0c;比较抽象。随便写写笔记。 跟着网上找的项目写写感觉这个项目还不错&#xff1a; 分享给码友 https://zh-hans.react.dev/learn/tutorial-tic-tac-toe 参…

未来一周比特币价格及数字货币市场预测

荷月的比特币市场就像过山车一样&#xff0c;仅仅六月下旬就跌去-12%&#xff0c;本周更是暴跌-6%&#xff0c;至 58,378美元。在这种市场表现&#xff0c;应有的踩踏如期而至。德国政府今日宣布再出售750 比特币的行为继续打击多头&#xff0c;但是小编认为这恰恰预示着市场可…