添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

本文描述了@Indexed注解 “未生效” 原因以及解决方案。

首先在这里明确一下知识点:只有当 @Document 和 @Indexed同时存在 ,使用mongoTemplate 或者 mongoRepository 传入 打了@Document注解的对象 时 才会自动创建索引

先上代码 ,下面的 “异常” 代码是否会自动创建索引呢?

//订单doc @Data @Accessors(chain = true) @FieldNameConstants @Document(collection = "order_") public class Order implements Serializable { private String id; @Indexed private String tid; @Indexed private String tradeId; private String status; private String created; //使用mongoTemplate做插入操作,按照月份分表 mongoTemplate.insert(orderRecord, mongoTemplate.getCollectionName(Order.class) + month);

答案是 :会的!

那为什么说是异常代码呢,因为它没有达到我的预期,这段代码会有两个问题:

1、会在mongodb里边创建两个 collection : order_ 和 order_${month}

2、索引会创建在 “order_” 这个collection里边,而不会在 “order_${month}”

这个时候答案就很明显了: 自动创建索引的时候 ,读取的collectionName 是 @Document注解里边的值,而不是 insert的时候传入的值

结论已经有了,就该看看它是怎么把传入的 collectionName弄丢的了

通过debug可以找到创建索引相关类以及方法的调用路径:

这个是方法签名:

checkForIndexes((MongoPersistentEntity<?>) entity) ;

最终只剩下了entity。通过entity的@Document注解来获取collectionName。细节就不贴图了,建议去debug下看看源码。

原因找到了,最终要如何解决当前的问题呢?上代码:

//字段索引 IndexOperations indexOps2 = mongoTemplate.indexOps(orderCollectionName); String[] indexFields2 = Arrays.stream(Order.class.getDeclaredFields()) .filter(f -> f.isAnnotationPresent(Indexed.class)) .map(Field::getName) .toArray(String[]::new); for (String indexField : indexFields2) { if (StringUtils.hasText(indexField)) { indexOps2.ensureIndex(new Index(indexField, Sort.Direction.ASC));

至此,问题解决。

最后提醒,别忘了把@Document注解去掉。原因文中已经说明。