支持动态字段查询与映射转换

- 新增 outputMetaFields 字段用于存储动态字段输出字段
- 修改 SearchRespConverter 中的转换方法,支持动态字段过滤与映射
- 更新 LambdaQueryWrapper 的 query 方法,处理动态字段输出逻辑
- 扩展 PropertyCache 缓存结构,增加动态字段相关集合与映射
- 优化 MilvusConverter 初始化逻辑,注册动态字段信息
This commit is contained in:
苑勇 2025-09-29 21:18:22 +08:00
parent fd9be066f9
commit 69eb4cc0c9
4 changed files with 51 additions and 14 deletions

View File

@ -1,7 +1,10 @@
package org.dromara.milvus.plus.cache;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author xgc
**/
@ -13,6 +16,9 @@ public class PropertyCache {
public Map<String, String> methodToPropertyMap = new HashMap<>(); //属性get方法名称->集合属性名称
public Set<String> metaFunctionSet = new HashSet<>(); //动态字段属性名称
public Map<String, String> metaMethodMap = new HashMap<>(); //属性get方法名称
// 根据值查找第一个匹配的键
public String findKeyByValue(String value) {

View File

@ -96,6 +96,8 @@ public class MilvusConverter {
if (Objects.isNull(fieldAnnotation)) {
if (collectionAnnotation.enableDynamicField()) {
propertyCache.functionToPropertyMap.put("$meta", "$meta");
propertyCache.metaFunctionSet.add(field.getName());
propertyCache.metaMethodMap.put(getGetMethodName(field), field.getName());
}
continue;
}

View File

@ -27,7 +27,7 @@ public class SearchRespConverter {
* @param entityType 指定的Java实体类类型用于将搜索结果的每个实体转换为该类型
* @return 转换后的MilvusResp对象其中包含了列表形式的搜索结果以及操作是否成功的标志
*/
public static <T> MilvusResp<List<MilvusResult<T>>> convertSearchRespToMilvusResp(SearchResp searchResp, Class<T> entityType) {
public static <T> MilvusResp<List<MilvusResult<T>>> convertSearchRespToMilvusResp(SearchResp searchResp, Class<T> entityType, List<String> outputMetaFields) {
// 从缓存中获取对应实体类型的转换缓存和属性缓存
ConversionCache conversionCache = MilvusCache.milvusCache.get(entityType.getName());
PropertyCache propertyCache = conversionCache.getPropertyCache();
@ -46,7 +46,11 @@ public class SearchRespConverter {
if (entry.getValue() == null) {
continue;
}
entityMap.putAll(GsonUtil.fromJsonToMap(entry.getValue().toString()));
Map<String, Object> metaMap = GsonUtil.fromJsonToMap(entry.getValue().toString());
//metaFunctionSet 类型匹配并完成 map 放入 entityMap 的操作
metaMap.entrySet().stream()
.filter(mapEntry -> propertyCache.metaFunctionSet.contains(String.valueOf(mapEntry.getKey())) && outputMetaFields.contains(mapEntry.getKey()))
.forEach(mapEntry -> entityMap.put(String.valueOf(mapEntry.getKey()), mapEntry.getValue()));
} else if(key!=null){
Object value = entry.getValue();
entityMap.put(key,value);
@ -75,10 +79,10 @@ public class SearchRespConverter {
* @param entityType 实体类型用于泛型结果的类型转换
* @return 返回一个包含Milvus结果列表的MilvusResp对象
*/
public static <T> MilvusResp<List<MilvusResult<T>>> convertGetRespToMilvusResp(QueryResp getResp, Class<T> entityType) {
public static <T> MilvusResp<List<MilvusResult<T>>> convertGetRespToMilvusResp(QueryResp getResp, Class<T> entityType, List<String> outputMetaFields) {
// 从QueryResp中提取查询结果
List<QueryResp.QueryResult> queryResults = getResp.getQueryResults();
return convertQuery(queryResults, entityType);
return convertQuery(queryResults, entityType, outputMetaFields);
}
public static MilvusResp<Long> convertGetRespToCount(QueryResp getResp) {
// 从QueryResp中提取查询结果
@ -92,10 +96,10 @@ public class SearchRespConverter {
* @param entityType 实体类型用于泛型结果的类型转换
* @return 返回一个包含Milvus结果列表的MilvusResp对象
*/
public static <T> MilvusResp<List<MilvusResult<T>>> convertGetRespToMilvusResp(GetResp getResp, Class<T> entityType) {
public static <T> MilvusResp<List<MilvusResult<T>>> convertGetRespToMilvusResp(GetResp getResp, Class<T> entityType, List<String> outputMetaFields) {
// 从GetResp中提取结果
List<QueryResp.QueryResult> getResults = getResp.getResults;
return convertQuery(getResults, entityType);
return convertQuery(getResults, entityType, outputMetaFields);
}
@ -106,7 +110,7 @@ public class SearchRespConverter {
* @param entityType 需要转换成的实体类型指定了转换的目标
* @return MilvusResp对象包含转换后的实体列表每个实体都包装在一个MilvusResult对象中同时设置成功状态为true
*/
private static <T> MilvusResp<List<MilvusResult<T>>> convertQuery(List<QueryResp.QueryResult> getResults, Class<T> entityType){
private static <T> MilvusResp<List<MilvusResult<T>>> convertQuery(List<QueryResp.QueryResult> getResults, Class<T> entityType, List<String> outputFields){
// 初始化转换缓存和属性缓存用于帮助将查询结果映射到Java实体
ConversionCache conversionCache = MilvusCache.milvusCache.get(entityType.getName());
PropertyCache propertyCache = conversionCache.getPropertyCache();
@ -119,7 +123,11 @@ public class SearchRespConverter {
// 通过属性缓存转换键名以适应Java实体的字段命名
for (Map.Entry<String, Object> entry : entityMap.entrySet()) {
String key = propertyCache.findKeyByValue(entry.getKey());
if(key!=null){
if (conversionCache.getMilvusEntity().getEnableDynamicField()
&& propertyCache.metaFunctionSet.contains(entry.getKey())
&& outputFields.contains(entry.getKey())) {
entityMap2.put(String.valueOf(entry.getKey()), entry.getValue());
} else if(key!=null){
Object value = entry.getValue();
entityMap2.put(key,value);
}

View File

@ -36,6 +36,7 @@ import java.util.stream.Collectors;
public class LambdaQueryWrapper<T> extends AbstractChainWrapper<T> implements Wrapper<LambdaQueryWrapper<T>, T> {
private ConversionCache conversionCache;
private List<String> outputFields;
private List<String> outputMetaFields;
private Class<T> entityType;
private String collectionName;
private String collectionAlias;
@ -977,18 +978,18 @@ public class LambdaQueryWrapper<T> extends AbstractChainWrapper<T> implements Wr
HybridSearchReq hybridSearchReq = buildHybrid();
log.info("Build HybridSearch Param--> {}", GsonUtil.toJson(hybridSearchReq));
SearchResp searchResp = client.hybridSearch(hybridSearchReq);
return SearchRespConverter.convertSearchRespToMilvusResp(searchResp, entityType);
return SearchRespConverter.convertSearchRespToMilvusResp(searchResp, entityType, outputMetaFields);
}
if (!vectors.isEmpty()) {
SearchReq searchReq = buildSearch();
log.info("Build Search Param--> {}", GsonUtil.toJson(searchReq));
SearchResp searchResp = client.search(searchReq);
return SearchRespConverter.convertSearchRespToMilvusResp(searchResp, entityType);
return SearchRespConverter.convertSearchRespToMilvusResp(searchResp, entityType, outputMetaFields);
} else {
QueryReq queryReq = buildQuery();
log.info("Build Query param--> {}", GsonUtil.toJson(queryReq));
QueryResp queryResp = client.query(queryReq);
return SearchRespConverter.convertGetRespToMilvusResp(queryResp, entityType);
return SearchRespConverter.convertGetRespToMilvusResp(queryResp, entityType, outputMetaFields);
}
},
"collection not loaded",
@ -1002,8 +1003,16 @@ public class LambdaQueryWrapper<T> extends AbstractChainWrapper<T> implements Wr
public MilvusResp<List<MilvusResult<T>>> query(FieldFunction<T, ?>... outputFields) throws MilvusException {
List<String> otf = new ArrayList<>();
for (FieldFunction<T, ?> outputField : outputFields) {
String methodName = outputField.getSerializedLambda(outputField).getImplMethodName();
if (conversionCache.getMilvusEntity().getEnableDynamicField() &&
conversionCache.getPropertyCache().metaMethodMap.containsKey(methodName)){
outputMetaFields = Optional.ofNullable(outputMetaFields).orElse(new ArrayList<>());
outputMetaFields.add(conversionCache.getPropertyCache().metaMethodMap.get(methodName));
otf.add("$meta");
} else {
otf.add(outputField.getFieldName(outputField));
}
}
this.outputFields = otf;
return query();
}
@ -1027,7 +1036,19 @@ public class LambdaQueryWrapper<T> extends AbstractChainWrapper<T> implements Wr
}
public MilvusResp<List<MilvusResult<T>>> query(String... outputFields) throws MilvusException {
this.outputFields = Arrays.stream(outputFields).collect(Collectors.toList());
this.outputFields = Arrays.stream(outputFields)
.map(field -> {
String milvusField = conversionCache.getPropertyCache().functionToPropertyMap.get(field);
if (milvusField == null &&
conversionCache.getMilvusEntity().getEnableDynamicField() &&
conversionCache.getPropertyCache().metaFunctionSet.contains(field)) {
outputMetaFields = Optional.ofNullable(outputMetaFields).orElse(new ArrayList<>());
outputMetaFields.add(field);
return "$meta";
}
return milvusField;
})
.collect(Collectors.toList());
return query();
}
@ -1041,7 +1062,7 @@ public class LambdaQueryWrapper<T> extends AbstractChainWrapper<T> implements Wr
GetReq getReq = builder.build();
GetResp getResp = client.get(getReq);
return SearchRespConverter.convertGetRespToMilvusResp(getResp, entityType);
return SearchRespConverter.convertGetRespToMilvusResp(getResp, entityType, outputMetaFields);
}
@Override