diff --git a/milvus-plus-boot-starter/src/main/java/io/github/javpower/milvus/plus/converter/MilvusEntityConverter.java b/milvus-plus-boot-starter/src/main/java/io/github/javpower/milvus/plus/converter/MilvusEntityConverter.java index 2d4c434..cb8ce5d 100644 --- a/milvus-plus-boot-starter/src/main/java/io/github/javpower/milvus/plus/converter/MilvusEntityConverter.java +++ b/milvus-plus-boot-starter/src/main/java/io/github/javpower/milvus/plus/converter/MilvusEntityConverter.java @@ -25,25 +25,45 @@ import java.util.Map; **/ public class MilvusEntityConverter { + /** + * 将Java实体类转换为MilvusEntity对象。 + * 该过程涉及读取实体类上的@MilvusCollection和@MilvusField注解,根据注解信息构建MilvusEntity对象, + * 同时缓存有关实体类与字段的映射信息和索引参数,以便后续使用。 + * + * @param entityClass 需要转换的Java实体类的Class对象。 + * @return 转换后的MilvusEntity对象,包含了Milvus表的结构信息和索引参数。 + * @throws IllegalArgumentException 如果实体类没有@MilvusCollection注解,则抛出异常。 + */ public static MilvusEntity convert(Class entityClass) { MilvusEntity milvus=new MilvusEntity(); + // 获取实体类上的@MilvusCollection注解,校验其存在性 MilvusCollection collectionAnnotation = entityClass.getAnnotation(MilvusCollection.class); if (collectionAnnotation == null) { throw new IllegalArgumentException("Entity must be annotated with @MilvusCollection"); } + // 从注解中读取集合(表)名称 String collectionName = collectionAnnotation.name(); milvus.setCollectionName(collectionName); + + // 初始化字段列表和索引参数列表 List milvusFields = new ArrayList<>(); List indexParams=new ArrayList<>(); + // 用于存储属性与函数映射的缓存 PropertyCache propertyCache=new PropertyCache(); + + // 遍历实体类的所有字段,读取@MilvusField注解信息 for (Field field : entityClass.getDeclaredFields()) { MilvusField fieldAnnotation = field.getAnnotation(MilvusField.class); if (fieldAnnotation != null) { + // 处理字段名,优先使用注解中的字段名,若无则用反射获取的字段名 String fieldName = fieldAnnotation.name().isEmpty() ? field.getName() : fieldAnnotation.name(); + // 缓存属性名与函数名的映射 propertyCache.functionToPropertyMap.put(field.getName(),fieldName); + // 处理主键字段 if (fieldAnnotation.isPrimaryKey()) { CollectionToPrimaryCache.collectionToPrimary.put(collectionName,fieldName); } + // 构建Milvus字段描述 AddFieldReq.AddFieldReqBuilder builder = AddFieldReq.builder() .fieldName(fieldName) .dataType(fieldAnnotation.dataType()) @@ -51,9 +71,11 @@ public class MilvusEntityConverter { .isPartitionKey(fieldAnnotation.isPartitionKey()) .elementType(fieldAnnotation.elementType()) .autoID(fieldAnnotation.autoID()); + // 如果存在描述,则添加 if(StringUtils.isNotEmpty(fieldAnnotation.description())){ builder.description(fieldAnnotation.description()); } + // 处理向量字段的维度、数组字段的最大长度、hash表的最大容量 if(fieldAnnotation.dimension()>0){ builder.dimension(fieldAnnotation.dimension()); } @@ -63,37 +85,53 @@ public class MilvusEntityConverter { if(fieldAnnotation.maxCapacity() > 0){ builder.maxCapacity(fieldAnnotation.maxCapacity()); } + // 构建字段对象并添加到列表 AddFieldReq milvusField = builder.build(); milvusFields.add(milvusField); - // 构建IndexParam对象 + // 根据字段信息构建索引参数对象 IndexParam indexParam = createIndexParam(field,fieldName); if(indexParam!=null){ indexParams.add(indexParam); } } } + // 设置Milvus字段和索引参数 milvus.setMilvusFields(milvusFields); milvus.setIndexParams(indexParams); - //缓存 + + // 缓存转换结果和集合信息 ConversionCache conversionCache=new ConversionCache(); conversionCache.setMilvusEntity(milvus); conversionCache.setCollectionName(collectionName); conversionCache.setPropertyCache(propertyCache); MilvusCache.milvusCache.put(entityClass,conversionCache); + return milvus; } + /** + * 根据字段信息和字段名称创建索引参数对象。 + * + * @param field 字段对象,需要包含MilvusIndex注解以用于索引配置。 + * @param fieldName 字段名称,用于构建索引参数时作为名称备用。 + * @return IndexParam 索引参数对象,如果字段没有MilvusIndex注解,则返回null。 + */ private static IndexParam createIndexParam(Field field,String fieldName) { + // 尝试获取字段上的MilvusIndex注解,用于后续索引参数的构建 MilvusIndex fieldAnnotation = field.getAnnotation(MilvusIndex.class); if (fieldAnnotation == null) { return null; } + + // 初始化额外参数映射,用于存储由extraParams注解提供的额外参数 Map map=new HashMap<>(); ExtraParam[] extraParams = fieldAnnotation.extraParams(); for (ExtraParam extraParam : extraParams) { map.put(extraParam.key(),extraParam.value()); } + + // 使用收集到的参数构建索引参数对象 return IndexParam.builder() .indexName(fieldAnnotation.indexName().isEmpty() ? fieldName : fieldAnnotation.indexName()) .fieldName(fieldName) @@ -104,4 +142,4 @@ public class MilvusEntityConverter { } -} \ No newline at end of file +} diff --git a/milvus-plus-boot-starter/src/main/java/io/github/javpower/milvus/plus/converter/SearchRespConverter.java b/milvus-plus-boot-starter/src/main/java/io/github/javpower/milvus/plus/converter/SearchRespConverter.java index c427750..9cfbda4 100644 --- a/milvus-plus-boot-starter/src/main/java/io/github/javpower/milvus/plus/converter/SearchRespConverter.java +++ b/milvus-plus-boot-starter/src/main/java/io/github/javpower/milvus/plus/converter/SearchRespConverter.java @@ -23,41 +23,55 @@ public class SearchRespConverter { private static final ObjectMapper objectMapper = new ObjectMapper(); + /** + * 将SearchResp对象转换为自定义的MilvusResp对象,其中SearchResp是Milvus搜索响应的内部结构, + * 而MilvusResp是对外提供的统一响应格式。该方法主要涉及将搜索结果中的每个实体从Map形式转换为指定的Java实体类T。 + * + * @param searchResp Milvus搜索操作的原始响应对象,包含搜索结果的详细信息。 + * @param entityType 指定的Java实体类类型,用于将搜索结果的每个实体转换为该类型。 + * @return 转换后的MilvusResp对象,其中包含了列表形式的搜索结果以及操作是否成功的标志。 + */ public static MilvusResp>> convertSearchRespToMilvusResp(SearchResp searchResp, Class entityType) { + // 从缓存中获取对应实体类型的转换缓存和属性缓存 ConversionCache conversionCache = MilvusCache.milvusCache.get(entityType); PropertyCache propertyCache = conversionCache.getPropertyCache(); + + // 获取原始搜索结果列表,并将其转换为MilvusResult类型的列表 List> searchResults = searchResp.getSearchResults(); - // 将searchResults中的每个SearchResult转换为MilvusResult List>> milvusResults = searchResults.stream() .map(innerList -> innerList.stream() .map(searchResult -> { try { - // 使用ObjectMapper将Map转换为Java实体类T + // 根据属性缓存,将实体Map中的键转换为对应的Java实体类字段名 Map entityMap = searchResult.getEntity(); Map entityMap2=new HashMap<>(); for (Map.Entry entry : entityMap.entrySet()) { String key = propertyCache.findKeyByValue(entry.getKey()); entityMap2.put(key,entry.getValue()); } + // 将转换后的Map转换为Java实体类T T entity = objectMapper.convertValue(entityMap2, entityType); + // 创建MilvusResult对象并设置相关字段 MilvusResult tMilvusResult = new MilvusResult<>(); tMilvusResult.setId(searchResult.getId()); tMilvusResult.setDistance(searchResult.getDistance()); tMilvusResult.setEntity(entity); return tMilvusResult; } catch (IllegalArgumentException e) { - // 处理转换错误 + // 抛出转换过程中的异常 throw new RuntimeException(e); } }) .collect(Collectors.toList())) .collect(Collectors.toList()); - List> results = milvusResults - .stream() // 从原始列表开始流操作 - .flatMap(List::stream) // 使用 flatMap 将嵌套列表展平 - .collect(Collectors.toList());// 收集结果到一个新的列表中 - // 创建MilvusResp对象并设置结果和成功标志 + // 将嵌套的列表展平为单个列表 + List> results = milvusResults + .stream() + .flatMap(List::stream) + .collect(Collectors.toList()); + + // 创建并填充MilvusResp对象 MilvusResp>> milvusResp = new MilvusResp<>(); milvusResp.setData(results); milvusResp.setSuccess(true); @@ -65,42 +79,70 @@ public class SearchRespConverter { return milvusResp; } + /** + * 将Get响应转换为Milvus响应的通用方法。 + * @param getResp Get操作的响应对象,可以是QueryResp或GetResp类型。 + * @param entityType 实体类型,用于泛型结果的类型转换。 + * @return 返回一个包含Milvus结果列表的MilvusResp对象。 + */ public static MilvusResp>> convertGetRespToMilvusResp(QueryResp getResp, Class entityType) { + // 从QueryResp中提取查询结果 List queryResults = getResp.getQueryResults(); - return convertQuery(queryResults,entityType); + return convertQuery(queryResults, entityType); } + + /** + * 将Get响应转换为Milvus响应的通用方法。 + * @param getResp Get操作的响应对象,可以是QueryResp或GetResp类型。 + * @param entityType 实体类型,用于泛型结果的类型转换。 + * @return 返回一个包含Milvus结果列表的MilvusResp对象。 + */ public static MilvusResp>> convertGetRespToMilvusResp(GetResp getResp, Class entityType) { + // 从GetResp中提取结果 List getResults = getResp.getResults; - return convertQuery(getResults,entityType); + return convertQuery(getResults, entityType); } - private static MilvusResp>> convertQuery(List getResults, Class entityType){ - // 解析GetResp中的查询结果 + + + /** + * 将查询结果转换为指定类型的实体列表。 + * + * @param getResults 查询结果列表,来自Milvus数据库的查询响应。 + * @param entityType 需要转换成的实体类型,指定了转换的目标。 + * @return MilvusResp对象,包含转换后的实体列表。每个实体都包装在一个MilvusResult对象中,同时设置成功状态为true。 + */ + private static MilvusResp>> convertQuery(List getResults, Class entityType){ + // 初始化转换缓存和属性缓存,用于帮助将查询结果映射到Java实体 ConversionCache conversionCache = MilvusCache.milvusCache.get(entityType); PropertyCache propertyCache = conversionCache.getPropertyCache(); List entities = new ArrayList<>(); - // 遍历每个查询结果,并将它们映射到Java实体类T的实例 + + // 遍历每个查询结果,映射到对应的Java实体 for (QueryResp.QueryResult queryResult : getResults) { Map entityMap = queryResult.getEntity(); Map entityMap2=new HashMap<>(); + // 通过属性缓存转换键名,以适应Java实体的字段命名 for (Map.Entry entry : entityMap.entrySet()) { String key = propertyCache.findKeyByValue(entry.getKey()); entityMap2.put(key,entry.getValue()); } - // 假设有一个方法可以从Map映射到实体类T,这个方法需要自定义实现 + // 使用转换工具将映射后的Map转换为指定类型的实体 T entity = objectMapper.convertValue(entityMap2, entityType); entities.add(entity); } + + // 将转换后的实体列表包装成MilvusResult对象,并收集到一个新的列表中 List> results = entities.stream().map(v -> { MilvusResult vo = new MilvusResult<>(); vo.setEntity(v); - vo.setDistance(0.0f); + vo.setDistance(0.0f); // 设置距离为0.0f,因为当前上下文未提供实际距离信息 return vo; }).collect(Collectors.toList()); - // 创建MilvusResp对象,并将实体列表作为其数据部分 + + // 构建并返回一个包含转换结果的MilvusResp对象,标记操作成功 MilvusResp>> milvusResp = new MilvusResp<>(); milvusResp.setData(results); milvusResp.setSuccess(true); - // 返回MilvusResp对象 return milvusResp; } -} \ No newline at end of file +}