| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- package com.zswl.dataservice.helper;
- import com.zswl.dataservice.domain.SuperEntity;
- import com.zswl.dataservice.utils.bean.BeanUtil;
- import lombok.SneakyThrows;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang3.reflect.FieldUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.domain.Sort;
- import org.springframework.data.mongodb.core.MongoTemplate;
- import org.springframework.data.mongodb.core.index.Index;
- import org.springframework.data.mongodb.core.index.IndexInfo;
- import org.springframework.data.mongodb.core.index.IndexOperations;
- import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
- import org.springframework.stereotype.Component;
- import java.lang.reflect.Field;
- import java.util.*;
- import java.util.stream.Collectors;
- /**
- * 重置索引
- */
- @Slf4j
- @Component
- public class ReIndexHelper {
- @Autowired
- private MongoTemplate mongoTemplate;
- //每个索引里最大数量
- private final static int MaxIndexCount = 24;
- /**
- * 重建索引
- */
- public void reIndexFromField(Class<? extends SuperEntity> entityClass, String fieldName, Class<?> cls) {
- //构建索引
- Set<Index> nowIndexNames = BeanUtil.readBeanType(cls).keySet()
- .stream()
- .map((it) -> {
- final String indexName = fieldName + "." + it;
- return new Index().named(indexName).on(indexName, Sort.Direction.ASC);
- }).collect(Collectors.toSet());
- //更新索引
- updateIndex(entityClass, fieldName, nowIndexNames.toArray(new Index[0]));
- }
- /**
- * 重置索引
- */
- public void reIndexFromMap(Class<? extends SuperEntity> entityClass, String fieldName) {
- //构建索引
- Set<Index> nowIndexNames = getIndexNamesFromMap(entityClass, fieldName)
- .stream()
- .map((it) -> {
- final String indexName = fieldName + "." + it;
- return new Index().named(indexName).on(indexName, Sort.Direction.ASC);
- }).collect(Collectors.toSet());
- //更新索引
- updateIndex(entityClass, fieldName, nowIndexNames.toArray(new Index[0]));
- }
- /**
- * 取出现有点索引
- *
- * @return
- */
- public Set<String> getIndexNames(String tableName) {
- //现有索引
- return this.mongoTemplate.indexOps(tableName)
- .getIndexInfo()
- .stream()
- .map((it) -> {
- return it.getName();
- }).collect(Collectors.toSet());
- }
- public void copyIndex(String tableName, String newTableName) {
- final IndexOperations indexOperations = this.mongoTemplate.indexOps(tableName);
- indexOperations.getIndexInfo().stream().filter(it -> !Set.of("_id_", "_id").contains(it.getName())).forEach((indexInfo) -> {
- final String indexName = indexInfo.getName();
- final IndexOperations newIndexOperations = this.mongoTemplate.indexOps(newTableName);
- //删除索引
- newIndexOperations.getIndexInfo().stream().filter(it -> indexName.equals(it.getName())).forEach((it) -> {
- newIndexOperations.dropIndex(it.getName());
- });
- final Index newIndex = new Index();
- newIndex.named(indexName);
- indexInfo.getIndexFields().forEach((it) -> {
- newIndex.on(it.getKey(), it.getDirection());
- });
- //创建索引
- newIndexOperations.ensureIndex(newIndex);
- });
- }
- /**
- * 取出现有点索引
- *
- * @param entityClass
- * @return
- */
- public Set<String> getIndexNames(Class<? extends SuperEntity> entityClass) {
- return this.getIndexNames(this.mongoTemplate.getCollectionName(entityClass));
- }
- /**
- * 更新索引
- *
- * @param tableName
- * @param indexs
- */
- @SneakyThrows
- public void updateIndex(String tableName, Index... indexs) {
- //现有索引
- final Set<String> nowIndexNames = getIndexNames(tableName);
- //索引
- final IndexOperations indexOperations = this.mongoTemplate.indexOps(tableName);
- //索引不存在建索引
- Arrays.stream(indexs).filter(it -> it.getIndexKeys().size() > 0).forEach((it) -> {
- String indexName = getIndexName(it);
- if ((nowIndexNames.contains(indexName))) {
- indexOperations.dropIndex(indexName);
- }
- String ret = indexOperations.ensureIndex(it);
- log.info("update index : " + ret);
- });
- }
- @SneakyThrows
- private String getIndexName(Index index) {
- final Field field = FieldUtils.getDeclaredField(Index.class, "name", true);
- if (field == null) {
- return null;
- }
- Object val = field.get(index);
- if (val == null) {
- return null;
- }
- return String.valueOf(val);
- }
- /**
- * 更新索引,独立的索引项
- *
- * @param entityClass
- * @param indexs
- */
- @SneakyThrows
- public void updateIndex(Class<? extends SuperEntity> entityClass, Index... indexs) {
- this.updateIndex(this.mongoTemplate.getCollectionName(entityClass), indexs);
- }
- /**
- * 更新索引,共用一个索引项
- *
- * @param entityClass
- */
- @SneakyThrows
- public void updateIndex(Class<? extends SuperEntity> entityClass, String indexName, Index... indexs) {
- boolean isUpdate = false;
- List<IndexInfo> indexInfos = this.mongoTemplate.indexOps(entityClass)
- .getIndexInfo()
- .stream()
- .filter((it) -> {
- return it.getName().length() > indexName.length() + 1 && it.getName().substring(0, indexName.length()).equals(indexName);
- }).collect(Collectors.toList());
- if (indexInfos != null && indexInfos.size() > 0) {
- isUpdate = isNeedUpdateIndex(indexInfos, indexs);
- } else {
- isUpdate = true;
- }
- //进行更新索引
- if (isUpdate) {
- final IndexOperations indexOperations = this.mongoTemplate.indexOps(entityClass);
- //如果存在则删除所有的和符合索引
- indexOperations.getIndexInfo().stream().filter((it) -> {
- return it.getName().length() > indexName.length() + 1 && it.getName().substring(0, indexName.length()).equals(indexName);
- }).forEach((it) -> {
- indexOperations.dropIndex(it.getName());
- });
- int size = (int) (indexs.length / MaxIndexCount);
- for (int i = 0; i < size; i++) {
- updateIndex(indexOperations, indexName + "_" + i, i, indexs);
- }
- if (indexs.length % MaxIndexCount != 0) {
- updateIndex(indexOperations, indexName + "_" + size, size, indexs);
- }
- }
- }
- @SneakyThrows
- private void updateIndex(IndexOperations indexOperations, String indexName, int page, final Index[] indexs) {
- Index index = new Index();
- index.named(indexName);
- for (int j = 0; j < MaxIndexCount; j++) {
- //索引
- int i = page * MaxIndexCount + j;
- if (i >= indexs.length) {
- continue;
- }
- Index it = indexs[i];
- Field field = it.getClass().getDeclaredField("name");
- field.setAccessible(true);
- String fieldName = String.valueOf(field.get(it));
- index.on(fieldName, Sort.Direction.ASC);
- }
- log.info("update index : {}", indexName);
- indexOperations.ensureIndex(index);
- }
- /**
- * 需要更新的名字
- *
- * @return
- */
- private boolean isNeedUpdateIndex(List<IndexInfo> indexInfos, Index[] indexs) {
- //取出需要更新的索引名
- Set<String> newUpdateNames = Arrays.stream(indexs).map((it) -> {
- return it.getIndexOptions().get("name");
- }).filter((it) -> {
- return it != null;
- }).map((it) -> {
- return String.valueOf(it);
- }).collect(Collectors.toSet());
- //取出现有的索引名
- Set<String> nowIndexName = new HashSet<>();
- indexInfos.forEach((it) -> {
- nowIndexName.addAll(it.getIndexFields().stream().map((index) -> {
- return index.getKey();
- }).collect(Collectors.toSet()));
- });
- for (String updateName : newUpdateNames) {
- if (!nowIndexName.contains(updateName)) {
- return true;
- }
- }
- return false;
- }
- /**
- * 取出Map属性对应的所有key的集合
- *
- * @return
- */
- public Set<String> getIndexNamesFromMap(Class<? extends SuperEntity> entityClass, String fieldName) {
- String collectionName = this.mongoTemplate.getCollectionName(entityClass);
- String map = "function(){if(this." + fieldName + "==null){return}for(var key in this." + fieldName + "){emit(key,1)}};";
- String reduce = "function(key,values){return values.length};";
- Set<String> indexNames = new HashSet<>();
- MapReduceResults<Map> mapReduceResults = this.mongoTemplate.mapReduce(collectionName, map, reduce, Map.class);
- mapReduceResults.forEach((it) -> {
- indexNames.add(String.valueOf(it.get("_id")));
- });
- return indexNames;
- }
- }
|