spring-data-elasticsearch使用笔记

一、定义document

@Data
@EqualsAndHashCode(callSuper = false)
@Document(indexName = "syni_sjb_encyclopedia_entry")
public class SjbEncyclopediaEntryDocument implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    private String id;

    /**
     * 词条名称
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer="ik_max_word")
    private String name;

    /**
     * 词条解释,富文本类型
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer="ik_max_word")
    private String entryExplain;

    /**
     * 初始浏览人数
     */
    @Field(type = FieldType.Integer)
    private Integer initPeopleCount;

    /**
     * 补增浏览人数
     */
    @Field(type = FieldType.Integer)
    private Integer complementPeopleCount;

    /**
     * 真实浏览人数,非实时
     */
    @Field(type = FieldType.Integer)
    private Integer realPeopleCount;

    /**
     * 初始人数+补增人数+真实浏览人数
     */
    @Field(type = FieldType.Integer)
    private Integer sumPeopleCount;

    /**
     * 词条生成的h5文件url
     */
    @Field(type = FieldType.Keyword)
    private String link;

    /**
     * 来源
     */
    @Field(type = FieldType.Keyword)
    private String createWay;

    /**
     * 创建人
     */
    @Field(type = FieldType.Keyword)
    private String creator;

    /**
     * 创建时间
     */
    @Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second)
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    @Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second)
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    private LocalDateTime updateTime;


}

这里有个坑:时间字段使用
@Field(type = FieldType.Date, format = DateFormat.custom, pattern = “yyyy-MM-dd HH:mm:ss”)
调用find时时间会反序列化失败,不知道是不是版本问题
我的版本是2.3.4 RELEASE

二、手动put es mapping(类似于建表,定义表结构)

put http://xxx.xxx.xx:9200/syni_sjb_encyclopedia_entry
{
    "mappings": {
        "properties": {
            "_class": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "complementPeopleCount": {
                "type": "integer"
            },
            "createTime": {
                "type": "date",
                "format": "yyyy-MM-dd'T'HH:mm:ss||yyyy-MM-dd||epoch_millis"
            },
            "createWay": {
                "type": "keyword"
            },
            "creator": {
                "type": "keyword"
            },
            "entryExplain": {
                "type": "text",
                "analyzer": "ik_max_word"
            },
            "initPeopleCount": {
                "type": "integer"
            },
            "link": {
                "type": "keyword"
            },
            "name": {
                "type": "text",
                "analyzer": "ik_max_word"
            },
            "realPeopleCount": {
                "type": "integer"
            },
            "sumPeopleCount": {
                "type": "integer"
            },
            "updateTime": {
                "type": "date",
                "format": "yyyy-MM-dd'T'HH:mm:ss||yyyy-MM-dd||epoch_millis"
            }
        }
    }
}

ES自带有自动建表的功能,那为什么还要手动put?
因为字段的类型可能不会合你意,比如时间格式只有yyyy-MM-dd’T’HH:mm:ss,但实际上还可能需要yyyy-MM-dd

三、创建respository,并定义方法(可省略)

public interface SjbEncyclopediaEntryRepository extends ElasticsearchRepository<SjbEncyclopediaEntryDocument,String> {

    List<SjbEncyclopediaEntryDocument> findByNameAndIdNot(String name, String id);
}

方法定义类似JPA(虽然我也没用过JPA,大概意思就是按照一定规范定义方法,框架就自动帮你实现,比如findByName)
这个不太好用,因为用这个就不知道怎么分页,怎么排序了。

四、ElasticsearchOperations使用及与Mybatis-plus方法的转换

我的需求是把mysql的数据转移到ES,功能不变。所以需要把Mybatis-plus的方法转化成ES

- 增删改

增:xxxService.save(entity) => elasticsearchOperations.save(entity)
改:xxxService.update(entity) => elasticsearchOperations.save(entity)
删:xxxService.removeById(id) => elasticsearchOperations.deleteById(id)

增和改同样是使用save,只要id一样就会自动覆盖。

- 查

查比较复杂,上一段代码大家看看前后对比

    public Page<SjbEncyclopediaEntryVO> queryByParam(SjbEncyclopediaEntryQueryDTO dto) {
    	// 分页
        Page<SjbEncyclopediaEntry> page = new Page<>(dto.getPageNo(), dto.getPageSize());
        QueryWrapper<SjbEncyclopediaEntry> queryWrapper = new QueryWrapper<>();
        if(StringUtils.isNotBlank(dto.getName())) {
            queryWrapper.lambda().eq(SjbEncyclopediaEntry::getName, dto.getName());
        }
        if(dto.getStartDate() != null && dto.getEndDate() != null) {
            queryWrapper.lambda().between(SjbEncyclopediaEntry::getCreateTime, dto.getStartDate(), dto.getEndDate().plusDays(1));
        }
        // 排序
        queryWrapper.lambda().orderByDesc(SjbEncyclopediaEntry::getRealPeopleCount);
        page = page(page, queryWrapper);
        Page<SjbEncyclopediaEntryVO> result = new Page<>(dto.getPageNo(), dto.getPageSize());
        BeanUtils.copyProperties(page, result);
        result.setRecords(page.getRecords().stream().map(sjbEncyclopediaEntry -> {
            SjbEncyclopediaEntryVO vo = new SjbEncyclopediaEntryVO();
            BeanUtils.copyProperties(sjbEncyclopediaEntry, vo);
            vo.setRealPeopleCount(getRedisRealPeopleCount(sjbEncyclopediaEntry.getId()));
            return vo;
        }).collect(Collectors.toList()));
        return result;
    }
    public Page<SjbEncyclopediaEntryVO> queryByParam(SjbEncyclopediaEntryQueryDTO dto) {
        Pageable pageable = PageRequest.of(dto.getPageNo()-1, dto.getPageSize());
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if(StringUtils.isNotBlank(dto.getName())) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("name", dto.getName()));
        }
        if(dto.getStartDate() != null && dto.getEndDate() != null) {
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("createTime").from(dto.getStartDate()).to(dto.getEndDate().plusDays(1)));
        }
        SortBuilder sortBuilder = SortBuilders.fieldSort("createTime").order(SortOrder.DESC);
        NativeSearchQuery build = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(pageable)
                .withSort(sortBuilder)
                .build();
        SearchHits<SjbEncyclopediaEntryDocument> search = elasticsearchOperations.search(build, SjbEncyclopediaEntryDocument.class);
        Page<SjbEncyclopediaEntryVO> result = new Page<>(dto.getPageNo(), dto.getPageSize());
        result.setTotal(search.getTotalHits());

        List<SearchHit<SjbEncyclopediaEntryDocument>> collect = search.get().collect(Collectors.toList());
        result.setRecords(collect.stream().map(sjbEncyclopediaEntry -> {
            SjbEncyclopediaEntryVO vo = new SjbEncyclopediaEntryVO();
            BeanUtils.copyProperties(sjbEncyclopediaEntry.getContent(), vo);
            vo.setRealPeopleCount(getRedisRealPeopleCount(sjbEncyclopediaEntry.getId()));
            return vo;
        }).collect(Collectors.toList()));
        return result;
    }

可以大致理解mybatis-plus与es的实体与api对应关系为:

QueryWrapper<?> => NativeSearchQuery
Page<?> => Pageable
wrapper.orderByDesc => SortBuilder
Page<?> result => List<SearchHit<?>>
page(page, queryWrapper); => elasticsearchOperations.search(build, SjbEncyclopediaEntryDocument.class);

五、一些坑

boolQueryBuilder.filter(QueryBuilders.rangeQuery(“publishTime”).lt(LocalDateTime.now()));
这句话又报错了,估计是lt里的时间值转字符串时多了毫秒值,试了mapping里加毫秒格式也不行。
解决方案:直接用字符串
String format = LocalDateTime.now().format(DateTimeFormatter.ofPattern(“yyyy-MM-dd’T’HH:mm:ss”));
boolQueryBuilder.filter(QueryBuilders.rangeQuery(“publishTime”).lt(format));

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
spring-data-elasticsearch官方教程文档提供了关于如何使用spring-data-elasticsearch框架进行Elasticsearch数据库操作的详细指导。该文档分为几个部分,包括介绍、快速入门、基本概念、查询构造器和复杂查询等。 文档的介绍部分简要介绍了spring-data-elasticsearch框架以及它提供的主要功能。快速入门部分通过一个简单的示例演示了如何配置spring-data-elasticsearch并进行基本的CRUD操作。该示例涵盖了创建索引、映射实体类、保存数据、查询数据以及删除数据。通过这个示例,读者可以迅速了解到spring-data-elasticsearch的基本用法。 基本概念部分详细介绍了spring-data-elasticsearch中的一些重要概念,包括实体类映射、索引操作、文档操作、字段映射、分页和排序等。这些概念对于深入理解spring-data-elasticsearch使用非常重要。 查询构造器部分介绍了spring-data-elasticsearch提供的查询构造器的使用方法。该部分通过实例演示了如何使用查询构造器进行基本查询、范围查询、模糊查询以及布尔查询等。读者可以通过这些示例快速掌握查询构造器的使用。 最后一部分是关于复杂查询的介绍。这一部分介绍了如何使用原生查询、使用注解进行查询以及使用自定义实现进行查询等。复杂查询是spring-data-elasticsearch一个非常重要的特性,通过它可以实现更加灵活和高级的查询功能。 总体来说,spring-data-elasticsearch官方教程文档提供了丰富的实例和详细的说明,对于想要学习和使用spring-data-elasticsearch框架的开发者来说,是一份非常有价值的指南。读者可以通过该文档逐步了解spring-data-elasticsearch的相关概念和基本用法,并通过实例演示快速上手。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值