diff --git a/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/conditions/LambdaInsertWrapper.java b/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/conditions/LambdaInsertWrapper.java index a5e2a77..ee82592 100644 --- a/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/conditions/LambdaInsertWrapper.java +++ b/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/conditions/LambdaInsertWrapper.java @@ -14,10 +14,7 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; /** * 构建器内部类,用于构建insert请求 @@ -87,10 +84,11 @@ public class LambdaInsertWrapper extends AbstractChainWrapper implements return resp; } - public MilvusResp insert(T ...t) throws MilvusException { + public MilvusResp insert(Iterator iterator) throws MilvusException { PropertyCache propertyCache = conversionCache.getPropertyCache(); List jsonObjects=new ArrayList<>(); - for (T t1 : t) { + while (iterator.hasNext()) { + T t1 = iterator.next(); Map propertiesMap = getPropertiesMap(t1); JSONObject jsonObject=new JSONObject(); for (Map.Entry entry : propertiesMap.entrySet()) { @@ -100,7 +98,6 @@ public class LambdaInsertWrapper extends AbstractChainWrapper implements jsonObject.put(tk,value); } jsonObjects.add(jsonObject); - } return insert(jsonObjects); } diff --git a/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/conditions/LambdaUpdateWrapper.java b/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/conditions/LambdaUpdateWrapper.java index c877d4a..9e5bc9b 100644 --- a/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/conditions/LambdaUpdateWrapper.java +++ b/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/conditions/LambdaUpdateWrapper.java @@ -18,6 +18,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -404,26 +405,29 @@ public class LambdaUpdateWrapper extends AbstractChainWrapper implements return resp; } - public MilvusResp updateById(T ...t) throws MilvusException { + public MilvusResp updateById(Iterator iterator) throws MilvusException { PropertyCache propertyCache = conversionCache.getPropertyCache(); String pk = CollectionToPrimaryCache.collectionToPrimary.get(collectionName); - List jsonObjects=new ArrayList<>(); - for (T t1 : t) { + List jsonObjects = new ArrayList<>(); + // 使用迭代器遍历可变参数 + while (iterator.hasNext()) { + T t1 = iterator.next(); Map propertiesMap = getPropertiesMap(t1); - JSONObject jsonObject=new JSONObject(); + JSONObject jsonObject = new JSONObject(); for (Map.Entry entry : propertiesMap.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); + // 根据PropertyCache转换属性名 String tk = propertyCache.functionToPropertyMap.get(key); - jsonObject.put(tk,value); + jsonObject.put(tk, value); } + // 检查是否包含主键 if (!jsonObject.containsKey(pk)) { - throw new MilvusException("not find primary key",400); + throw new MilvusException("not find primary key", 400); } jsonObjects.add(jsonObject); - } - return update(jsonObjects); + return update(jsonObjects); } @Override diff --git a/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/mapper/BaseMilvusMapper.java b/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/mapper/BaseMilvusMapper.java index 647e874..e795666 100644 --- a/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/mapper/BaseMilvusMapper.java +++ b/milvus-plus-core/src/main/java/org/dromara/milvus/plus/core/mapper/BaseMilvusMapper.java @@ -15,7 +15,10 @@ import org.dromara.milvus.plus.model.vo.MilvusResult; import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.util.Collection; +import java.util.Iterator; import java.util.List; +import java.util.NoSuchElementException; /** * @author xgc @@ -58,6 +61,25 @@ public abstract class BaseMilvusMapper{ public LambdaInsertWrapper insertWrapper() { return lambda(new LambdaInsertWrapper<>()); } + private static class ArrayIterator implements Iterator { + private final T[] array; + private int index = 0; + + public ArrayIterator(T[] array) { + this.array = array; + } + + @Override + public boolean hasNext() { + return index < array.length; + } + + @Override + public T next() { + if (!hasNext()) throw new NoSuchElementException(); + return array[index++]; + } + } public MilvusResp>> getById(Serializable ... ids) { @@ -68,15 +90,25 @@ public abstract class BaseMilvusMapper{ LambdaDeleteWrapper lambda = deleteWrapper(); return lambda.removeById(ids); } - public MilvusResp updateById(T ... entity){ - LambdaUpdateWrapper lambda = updateWrapper(); - return lambda.updateById(entity); - } public MilvusResp insert(T ... entity){ LambdaInsertWrapper lambda = insertWrapper(); - return lambda.insert(entity); + Iterator iterator = new ArrayIterator<>(entity); + return lambda.insert(iterator); + } + public MilvusResp insert(Collection entity){ + LambdaInsertWrapper lambda = insertWrapper(); + return lambda.insert(entity.iterator()); } + public MilvusResp updateById(T... entity) { + LambdaUpdateWrapper lambda = updateWrapper(); + Iterator iterator = new ArrayIterator<>(entity); + return lambda.updateById(iterator); + } + public MilvusResp updateById(Collection entity) { + LambdaUpdateWrapper lambda = updateWrapper(); + return lambda.updateById(entity.iterator()); + } /** * 创建通用构建器实例 @@ -99,7 +131,4 @@ public abstract class BaseMilvusMapper{ wrapper.init(collectionName,client, conversionCache, entityType); return wrapper.wrapper(); } - - - } \ No newline at end of file diff --git a/milvus-plus-core/src/main/java/org/dromara/milvus/plus/service/AbstractMilvusClientBuilder.java b/milvus-plus-core/src/main/java/org/dromara/milvus/plus/service/AbstractMilvusClientBuilder.java index 42642ca..f67c482 100644 --- a/milvus-plus-core/src/main/java/org/dromara/milvus/plus/service/AbstractMilvusClientBuilder.java +++ b/milvus-plus-core/src/main/java/org/dromara/milvus/plus/service/AbstractMilvusClientBuilder.java @@ -1,12 +1,13 @@ package org.dromara.milvus.plus.service; -import org.dromara.milvus.plus.annotation.MilvusCollection; -import org.dromara.milvus.plus.cache.CollectionToPrimaryCache; -import org.dromara.milvus.plus.model.MilvusProperties; import io.milvus.v2.client.ConnectConfig; import io.milvus.v2.client.MilvusClientV2; import io.milvus.v2.service.collection.request.ReleaseCollectionReq; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.dromara.milvus.plus.annotation.MilvusCollection; +import org.dromara.milvus.plus.cache.CollectionToPrimaryCache; +import org.dromara.milvus.plus.model.MilvusProperties; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; @@ -15,23 +16,19 @@ import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.util.ClassUtils; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; @Slf4j public abstract class AbstractMilvusClientBuilder implements MilvusClientBuilder, ICMService { + @Setter protected MilvusProperties properties; protected MilvusClientV2 client; - private final static String CLASS="*.class"; + private final static String CLASS = "*.class"; - public void setProperties(MilvusProperties properties) { - this.properties = properties; - } - @Override public void initialize() { if (properties.isEnable()) { @@ -53,7 +50,7 @@ public abstract class AbstractMilvusClientBuilder implements MilvusClientBuilder if (client != null) { //释放集合+释放client Set co = CollectionToPrimaryCache.collectionToPrimary.keySet(); - if(co.size()>0){ + if (!co.isEmpty()) { for (String name : co) { ReleaseCollectionReq releaseCollectionReq = ReleaseCollectionReq.builder() .collectionName(name) @@ -67,11 +64,12 @@ public abstract class AbstractMilvusClientBuilder implements MilvusClientBuilder } - public void handler(){ - if(client!=null){ - List> classes = getClass(properties.getPackages()); - performBusinessLogic(classes); + public void handler() { + if (Objects.isNull(client)) { + log.warn("initialize handler over!"); } + List> classes = getClass(properties.getPackages()); + performBusinessLogic(classes); } @Override @@ -80,31 +78,36 @@ public abstract class AbstractMilvusClientBuilder implements MilvusClientBuilder } //获取指定包下实体类 - private List> getClass(List packages){ - List> res=new ArrayList<>(); + private List> getClass(List packages) { ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); - for (String pg : packages) { - String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + - ClassUtils.convertClassNameToResourcePath(pg+".") + CLASS; - try { - Resource[] resources = resourcePatternResolver.getResources(pattern); - MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver); - for (Resource resource : resources) { - MetadataReader reader = readerFactory.getMetadataReader(resource); - String classname = reader.getClassMetadata().getClassName(); - Class clazz = Class.forName(classname); - MilvusCollection annotation = clazz.getAnnotation(MilvusCollection.class); - if(annotation!=null){ - res.add(clazz); + return Optional.ofNullable(packages) + .orElseThrow(() -> new RuntimeException("model package is null, please configure the [packages] parameter")) + .stream() + .map(pg -> { + List> res = new ArrayList<>(); + String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + ClassUtils.convertClassNameToResourcePath(pg + ".") + CLASS; + try { + Resource[] resources = resourcePatternResolver.getResources(pattern); + MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver); + for (Resource resource : resources) { + MetadataReader reader = readerFactory.getMetadataReader(resource); + String classname = reader.getClassMetadata().getClassName(); + Class clazz = Class.forName(classname); + MilvusCollection annotation = clazz.getAnnotation(MilvusCollection.class); + if (annotation != null) { + res.add(clazz); + } + } + } catch (Exception e) { + throw new RuntimeException(e); } - } - }catch (Exception e){ - e.printStackTrace(); - } - } - return res; + return res; + }).flatMap(Collection::stream) + .collect(Collectors.toList()); } - //缓存+是否构建集合 + + //缓存 + 是否构建集合 public void performBusinessLogic(List> annotatedClasses) { for (Class milvusClass : annotatedClasses) { createCollection(milvusClass); diff --git a/milvus-plus-core/src/main/java/org/dromara/milvus/plus/service/MilvusClientBuilder.java b/milvus-plus-core/src/main/java/org/dromara/milvus/plus/service/MilvusClientBuilder.java index 24ebb69..eb87b66 100644 --- a/milvus-plus-core/src/main/java/org/dromara/milvus/plus/service/MilvusClientBuilder.java +++ b/milvus-plus-core/src/main/java/org/dromara/milvus/plus/service/MilvusClientBuilder.java @@ -3,7 +3,20 @@ package org.dromara.milvus.plus.service; import io.milvus.v2.client.MilvusClientV2; public interface MilvusClientBuilder { + /** + * 初始化 + */ void initialize(); + + /** + * 关闭客户端 + */ void close() throws InterruptedException; + + /** + * 获取milvus客户端 + * + * @return MilvusClientV2 + */ MilvusClientV2 getClient(); } \ No newline at end of file diff --git a/milvus-spring-demo/src/main/java/org/dromara/milvus/demo/ApplicationRunnerTest.java b/milvus-spring-demo/src/main/java/org/dromara/milvus/demo/ApplicationRunnerTest.java index c15b94b..eaf3da7 100644 --- a/milvus-spring-demo/src/main/java/org/dromara/milvus/demo/ApplicationRunnerTest.java +++ b/milvus-spring-demo/src/main/java/org/dromara/milvus/demo/ApplicationRunnerTest.java @@ -1,18 +1,20 @@ package org.dromara.milvus.demo; import com.alibaba.fastjson.JSONObject; -import org.dromara.milvus.demo.model.Face; -import org.dromara.milvus.demo.test.FaceMilvusMapper; -import org.dromara.milvus.plus.model.vo.MilvusResp; -import org.dromara.milvus.plus.model.vo.MilvusResult; import io.milvus.v2.service.vector.response.InsertResp; import lombok.extern.slf4j.Slf4j; +import org.dromara.milvus.demo.mapper.FaceMilvusMapper; +import org.dromara.milvus.demo.model.Face; +import org.dromara.milvus.plus.model.vo.MilvusResp; +import org.dromara.milvus.plus.model.vo.MilvusResult; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; -import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.LongStream; @Component @Slf4j @@ -24,53 +26,58 @@ public class ApplicationRunnerTest implements ApplicationRunner { } @Override - public void run(ApplicationArguments args){ - face(); + public void run(ApplicationArguments args) { + insertFace(); + getByIdTest(); + vectorQuery(); + scalarQuery(); } - private void face(){ - Face face=new Face(); - List vector = new ArrayList<>(); - for (int i = 0; i < 128; i++) { - vector.add((float) (Math.random() * 100)); // 这里仅作为示例使用随机数 - } - face.setPersonId(1l); - face.setFaceVector(vector); + + private void insertFace() { + List faces = LongStream.range(1, 10) + .mapToObj(i -> { + Face faceTmp = new Face(); + faceTmp.setPersonId(i); + List vectorTmp = IntStream.range(0, 128) + .mapToObj(j -> (float) (Math.random() * 100)) + .collect(Collectors.toList()); + faceTmp.setFaceVector(vectorTmp); + faceTmp.setPersonName(i % 2 == 0 ? "张三" + i : "李四" + i); + return faceTmp; + }) + .collect(Collectors.toList()); //新增 - List faces=new ArrayList<>(); - for (int i = 1; i < 10 ;i++){ - Face face1=new Face(); - face1.setPersonId(Long.valueOf(i)); - List vector1 = new ArrayList<>(); - for (int j = 0; j < 128; j++) { - vector1.add((float) (Math.random() * 100)); // 这里仅作为示例使用随机数 - } - face1.setFaceVector(vector1); - if(i%2==0){ - face1.setPersonName("张三"+i); - }else { - face1.setPersonName("李四"+i); - } - faces.add(face1); - } - MilvusResp insert = mapper.insertWrapper().partition("face_001").insert(faces.toArray(new Face[0])); + MilvusResp insert = mapper.insertWrapper() + .partition("face_001") + .insert(faces.iterator()); log.info("insert--{}", JSONObject.toJSONString(insert)); - //MilvusResp insert = mapper.insert(faces.toArray(faces.toArray(new Face[0]))); log.info("insert--{}", JSONObject.toJSONString(insert)); + } + + public void getByIdTest() { //id查询 - MilvusResp>> query = mapper.getById(9l); + MilvusResp>> query = mapper.getById(9L); log.info("query--getById---{}", JSONObject.toJSONString(query)); + } + + public void vectorQuery() { //向量查询 + List vector = IntStream.range(0, 128) + .mapToObj(i -> (float) (Math.random() * 100)) + .collect(Collectors.toList()); MilvusResp>> query1 = mapper.queryWrapper() .vector(Face::getFaceVector, vector) .like(Face::getPersonName, "张三") .topK(3) .query(); log.info("向量查询 query--queryWrapper---{}", JSONObject.toJSONString(query1)); + } + + public void scalarQuery() { //标量查询 MilvusResp>> query2 = mapper.queryWrapper() .eq(Face::getPersonId, 2L) - .limit(3l) + .limit(3L) .query(); log.info("标量查询 query--queryWrapper---{}", JSONObject.toJSONString(query2)); - } } \ No newline at end of file diff --git a/milvus-spring-demo/src/main/java/org/dromara/milvus/demo/test/FaceMilvusMapper.java b/milvus-spring-demo/src/main/java/org/dromara/milvus/demo/mapper/FaceMilvusMapper.java similarity index 84% rename from milvus-spring-demo/src/main/java/org/dromara/milvus/demo/test/FaceMilvusMapper.java rename to milvus-spring-demo/src/main/java/org/dromara/milvus/demo/mapper/FaceMilvusMapper.java index e599454..c33bd92 100644 --- a/milvus-spring-demo/src/main/java/org/dromara/milvus/demo/test/FaceMilvusMapper.java +++ b/milvus-spring-demo/src/main/java/org/dromara/milvus/demo/mapper/FaceMilvusMapper.java @@ -1,4 +1,4 @@ -package org.dromara.milvus.demo.test; +package org.dromara.milvus.demo.mapper; import org.dromara.milvus.demo.model.Face; import org.dromara.milvus.plus.mapper.MilvusMapper;