Mongo分表动态索引建立

Mongo分表动态索引建立


工作中经常遇到Mongo需要分表的情况。但是分表后,不能再使用spring date的@Document系列注解为mongo建立model和索引了。这时候需要动态建立索引和指定collection。


其实很简单,这里主要是做个笔记,免得忘记。

//PostConstruct注解执行在bean注入之后
@PostConstruct
private void init() {
    //建立索引字段
    Document document = new Document().append(UID, 1).append(ROOM_ID, 1);
    //配置建立索引
    Index idxUidRoomId = new CompoundIndexDefinition(document).background().named("idx_uid_roomId").unique();
    //建立,createAllCollectionName()是需要建立索引的collection name list
    createAllCollectionName().stream().map(mongoTemplate::indexOps)
            .forEach(it -> it.ensureIndex(idxUidRoomId));
}

save

public void saveTagsAndScore(Long toUid, Long roomId, Integer score, List<String> tags) {
    Query query = Query.query(Criteria.where(UID).is(toUid).and(ROOM_ID).is(roomId));

    Update update = new Update();
    update.inc(SCORE_TIMES, 1);
    update.inc(SCORE, score);
    tags.stream().forEach(tag -> {
        update.inc(TAGS + "." + tag, 1);
    });

    mongoTemplate.upsert(query, update, TagsAndScoreEntity.class, createTagsAndScoreCollectionName(roomId));
}

Query

public List<TagsAndScoreEntity> findTagsAndScore(List<Long> uids, Long roomID) {
    Query query = Query.query(Criteria.where(UID).in(uids).and(ROOM_ID).is(roomID));

    return mongoTemplate.find(query, TagsAndScoreEntity.class, createTagsAndScoreCollectionName(roomID));
}

常用的两种分表方式,按照时间和按照uid取余.

private static final int TAG_SAND_SCORE_SHARDING_NUM = 10;

private static final String SCORE_DETAILS_COLLECTION_NAME_PREFIX = "score_details_";
private static final String TAGS_AND_SCORE_COL_NAME_PREFIX = "tags_and_score_";

public static String createScoreDetailCollectionName() {
    return SCORE_DETAILS_COLLECTION_NAME_PREFIX + LocalDate.now().format(DateHelper.yyyyMM);
}

public static String createTagsAndScoreCollectionName(long roomId) {
    return TAGS_AND_SCORE_COL_NAME_PREFIX + (roomId % TAG_SAND_SCORE_SHARDING_NUM);
}

LocalDate这个类挺好用的。很简便。