milvus-logo
LFAI
홈페이지
  • 사용자 가이드

이터레이터 사용

Milvus는 대량의 엔티티로 결과를 반복하기 위한 검색 및 쿼리 반복기를 제공합니다. Milvus는 TopK를 16384로 제한하므로 사용자는 반복기를 사용하여 일괄 모드에서 컬렉션의 많은 수 또는 전체 엔티티를 반환할 수 있습니다.

개요

반복기는 기본 키 값과 부울 표현식을 사용하여 컬렉션 내의 대량의 데이터 또는 모든 데이터를 반복할 수 있는 강력한 도구입니다. 이를 통해 데이터를 검색하는 방식을 크게 개선할 수 있습니다. 시간이 지나면서 효율성이 떨어질 수 있는 기존의 오프셋제한 매개변수 사용과 달리, 반복기는 보다 확장 가능한 솔루션을 제공합니다.

반복기 사용의 이점

  • 단순성: 복잡한 오프셋제한 설정이 필요 없습니다.

  • 효율성: 필요한 데이터만 가져와서 확장 가능한 데이터 검색을 제공합니다.

  • 일관성: 부울 필터로 일관된 데이터 세트 크기를 보장합니다.

참고

  • 이 기능은 Milvus 2.3.x 이상에서 사용할 수 있습니다.

준비 단계

다음 단계에서는 Milvus에 연결하고, 컬렉션을 빠르게 설정하고, 무작위로 생성된 10,000개 이상의 엔티티를 컬렉션에 삽입하기 위해 코드의 용도를 변경합니다.

1단계: 컬렉션 만들기

를 사용하여 MilvusClient 을 사용하여 Milvus 서버에 연결하고 create_collection() 를 사용하여 컬렉션을 만듭니다.

사용 MilvusClientV2 을 사용하여 Milvus 서버에 연결하고 createCollection() 를 사용하여 컬렉션을 만듭니다.

from pymilvus import MilvusClient

# 1. Set up a Milvus client
client = MilvusClient(
    uri="http://localhost:19530"
)

# 2. Create a collection
client.create_collection(
    collection_name="quick_setup",
    dimension=5,
)
import io.milvus.client.MilvusServiceClient;
import io.milvus.param.ConnectParam;
import io.milvus.param.highlevel.collection.CreateSimpleCollectionParam;

String CLUSTER_ENDPOINT = "http://localhost:19530";

// 1. Connect to Milvus server
ConnectParam connectParam = ConnectParam.newBuilder()
        .withUri(CLUSTER_ENDPOINT)
        .build();

MilvusServiceClient client  = new MilvusServiceClient(connectParam);

// 2. Create a collection
CreateSimpleCollectionParam createCollectionParam = CreateSimpleCollectionParam.newBuilder()
        .withCollectionName("quick_setup")
        .withDimension(5)
        .build();

client.createCollection(createCollectionParam);

2단계: 무작위로 생성된 엔티티 삽입하기

를 사용하여 insert() 를 사용하여 컬렉션에 엔티티를 삽입합니다.

사용 insert() 를 사용하여 컬렉션에 엔티티를 삽입합니다.

# 3. Insert randomly generated vectors 
colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
data = []

for i in range(10000):
    current_color = random.choice(colors)
    current_tag = random.randint(1000, 9999)
    data.append({
        "id": i,
        "vector": [ random.uniform(-1, 1) for _ in range(5) ],
        "color": current_color,
        "tag": current_tag,
        "color_tag": f"{current_color}_{str(current_tag)}"
    })

print(data[0])

# Output
#
# {
#     "id": 0,
#     "vector": [
#         -0.5705990742218152,
#         0.39844925120642083,
#         -0.8791287928610869,
#         0.024163154953680932,
#         0.6837669917169638
#     ],
#     "color": "purple",
#     "tag": 7774,
#     "color_tag": "purple_7774"
# }

res = client.insert(
    collection_name="quick_setup",
    data=data,
)

print(res)

# Output
#
# {
#     "insert_count": 10000,
#     "ids": [
#         0,
#         1,
#         2,
#         3,
#         4,
#         5,
#         6,
#         7,
#         8,
#         9,
#         "(9990 more items hidden)"
#     ]
# }
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import com.alibaba.fastjson.JSONObject;

import io.milvus.param.R;
import io.milvus.param.dml.InsertParam;
import io.milvus.response.MutationResultWrapper;
import io.milvus.grpc.MutationResult;


// 3. Insert randomly generated vectors into the collection
List<String> colors = Arrays.asList("green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey");
List<JSONObject> data = new ArrayList<>();

for (int i=0; i<10000; i++) {
    Random rand = new Random();
    String current_color = colors.get(rand.nextInt(colors.size()-1));
    JSONObject row = new JSONObject();
    row.put("id", Long.valueOf(i));
    row.put("vector", Arrays.asList(rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
    row.put("color_tag", current_color + "_" + String.valueOf(rand.nextInt(8999) + 1000));
    data.add(row);
}

InsertParam insertParam = InsertParam.newBuilder()
    .withCollectionName("quick_setup")
    .withRows(data)
    .build();

R<MutationResult> insertRes = client.insert(insertParam);

if (insertRes.getStatus() != R.Status.Success.getCode()) {
    System.err.println(insertRes.getMessage());
}

MutationResultWrapper wrapper = new MutationResultWrapper(insertRes.getData());
System.out.println(wrapper.getInsertCount());

반복기를 사용한 검색

반복기를 사용하면 유사도 검색을 더욱 확장할 수 있습니다.

반복기를 사용하여 검색하려면 search_iterator() 메서드를 호출합니다:

이터레이터로 검색하려면 searchIterator() 메서드를 호출합니다:

  1. 검색 이터레이터를 초기화하여 검색 매개변수와 출력 필드를 정의합니다.

  2. 루프 내에서 next() 메서드를 사용하여 검색 결과를 페이지 매김합니다.

    • 메서드가 빈 배열을 반환하면 루프가 종료되고 더 이상 페이지를 사용할 수 없습니다.

    • 모든 결과에는 지정된 출력 필드가 포함됩니다.

  3. 모든 데이터가 검색되면 close() 메서드를 수동으로 호출하여 반복기를 닫습니다.

from pymilvus import Collection

# 4. Search with iterator
connections.connect(host="127.0.0.1", port=19530)
collection = Collection("quick_setup")

query_vectors = [[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]]
search_params = {
    "metric_type": "IP",
    "params": {"nprobe": 10}
}

iterator = collection.search_iterator(
    data=query_vectors,
    anns_field="vector",
    batch_size=10,
    param=search_params,
    output_fields=["color_tag"],
    limit=3
)

results = []

while True:
    result = iterator.next()
    if not result:
        iterator.close()
        break
        
    results.extend(result)
    
    for hit in result:
        results.append(hit.to_dict())

print(results)

# Output
#
# [
#     {
#         "id": 1756,
#         "distance": 2.0642056465148926,
#         "entity": {
#             "color_tag": "black_9109"
#         }
#     },
#     {
#         "id": 6488,
#         "distance": 1.9437453746795654,
#         "entity": {
#             "color_tag": "purple_8164"
#         }
#     },
#     {
#         "id": 3338,
#         "distance": 1.9107104539871216,
#         "entity": {
#             "color_tag": "brown_8121"
#         }
#     }
# ]
import io.milvus.param.dml.QueryIteratorParam;
import io.milvus.param.dml.SearchIteratorParam;
import io.milvus.response.QueryResultsWrapper;
import io.milvus.orm.iterator.SearchIterator;

// 4. Search with iterators
SearchIteratorParam iteratorParam = SearchIteratorParam.newBuilder()
    .withCollectionName("quick_setup")
    .withVectorFieldName("vector")
    // Use withFloatVectors() in clusters compatible with Milvus 2.4.x
    .withVectors(Arrays.asList(0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f))
    .withBatchSize(10L)
    .withParams("{\"metric_type\": \"COSINE\", \"params\": {\"level\": 1}}")
    .build();
        

R<SearchIterator> searchIteratorRes = client.searchIterator(iteratorParam);

if (searchIteratorRes.getStatus() != R.Status.Success.getCode()) {
    System.err.println(searchIteratorRes.getMessage());
}

SearchIterator searchIterator = searchIteratorRes.getData();
List<QueryResultsWrapper.RowRecord> results = new ArrayList<>();

while (true) {
    List<QueryResultsWrapper.RowRecord> batchResults = searchIterator.next();
    if (batchResults.isEmpty()) {
        searchIterator.close();
        break;
    }
    for (QueryResultsWrapper.RowRecord rowRecord : batchResults) {
        results.add(rowRecord);
    }
}

System.out.println(results.size());
파라미터 설명
data 벡터 임베딩의 목록.
Milvus는 지정된 임베딩과 가장 유사한 벡터 임베딩을 검색합니다.
anns_field 현재 컬렉션에 있는 벡터 필드의 이름입니다.
batch_size 현재 반복기에서 next() 을 호출할 때마다 반환할 엔티티의 수.
기본값은 1000입니다. 적절한 값으로 설정하여 반복당 반환할 엔티티 수를 제어합니다.
param 이 작업과 관련된 매개변수 설정
  • metric_type: 이 작업에 적용되는 메트릭 유형입니다. 위에서 지정한 벡터 필드를 인덱싱할 때 사용한 것과 동일해야 합니다. 사용 가능한 값은 L2, IP, COSINE, JACCARD, HAMMING입니다.
  • params: 추가 매개변수. 자세한 내용은 search_iterator()를 참조하세요.
output_fields 반환 시 각 엔티티에 포함할 필드 이름 목록.
기본값은 None입니다. 지정하지 않으면 기본 필드만 포함됩니다.
limit 반환할 총 엔티티 수.
기본값은 -1로, 일치하는 모든 엔티티가 반환됨을 나타냅니다.
매개변수 설명
withCollectionName 컬렉션 이름을 설정합니다. 컬렉션 이름은 비어 있거나 null일 수 없습니다.
withVectorFieldName 대상 벡터 필드를 이름으로 설정합니다. 필드 이름은 비어 있거나 null일 수 없습니다.
withVectors 대상 벡터를 설정합니다. 최대 16384개의 벡터가 허용됩니다.
withBatchSize 현재 반복자에서 next() 을 호출할 때마다 반환할 엔티티 수입니다.
기본값은 1000입니다. 적절한 값으로 설정하여 반복당 반환할 엔티티 수를 제어하세요.
withParams 검색 매개변수를 JSON 형식으로 지정합니다. 자세한 내용은 searchIterator()를 참조하세요.

반복기를 사용한 쿼리

이터레이터로 쿼리하려면 query_iterator() 메서드를 호출합니다:

이터레이터로 쿼리하려면 쿼리이터레이터() 메서드를 호출합니다:

# 6. Query with iterator
iterator = collection.query_iterator(
    batch_size=10, # Controls the size of the return each time you call next()
    expr="color_tag like \"brown_8\"",
    output_fields=["color_tag"]
)

results = []

while True:
    result = iterator.next()
    if not result:
        iterator.close()
        break
        
    results.extend(result)
    
# 8. Check the search results
print(len(results))

print(results[:3])

# Output
#
# [
#     {
#         "color_tag": "brown_8785",
#         "id": 94
#     },
#     {
#         "color_tag": "brown_8568",
#         "id": 176
#     },
#     {
#         "color_tag": "brown_8721",
#         "id": 289
#     }
# ]
import io.milvus.param.dml.QueryIteratorParam;
import io.milvus.orm.iterator.QueryIterator;

// 5. Query with iterators

try {
    Files.write(Path.of("results.json"), JSON.toJSONString(new ArrayList<>()).getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
} catch (Exception e) {
    // TODO: handle exception
    e.printStackTrace();
}

QueryIteratorParam queryIteratorParam = QueryIteratorParam.newBuilder()
    .withCollectionName("quick_setup")
    .withExpr("color_tag like \"brown_8%\"")
    .withBatchSize(50L)
    .addOutField("vector")
    .addOutField("color_tag")
    .build();

R<QueryIterator> queryIteratRes = client.queryIterator(queryIteratorParam);

if (queryIteratRes.getStatus() != R.Status.Success.getCode()) {
    System.err.println(queryIteratRes.getMessage());
}

QueryIterator queryIterator = queryIteratRes.getData();

while (true) {
    List<QueryResultsWrapper.RowRecord> batchResults = queryIterator.next();
    if (batchResults.isEmpty()) {
        queryIterator.close();
        break;
    }

    String jsonString = "";
    List<JSONObject> jsonObject = new ArrayList<>();
    try {
        jsonString = Files.readString(Path.of("results.json"));
        jsonObject = JSON.parseArray(jsonString).toJavaList(null);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    for (QueryResultsWrapper.RowRecord queryResult : batchResults) {
        JSONObject row = new JSONObject();
        row.put("id", queryResult.get("id"));
        row.put("vector", queryResult.get("vector"));
        row.put("color_tag", queryResult.get("color_tag"));
        jsonObject.add(row);
    }

    try {
        Files.write(Path.of("results.json"), JSON.toJSONString(jsonObject).getBytes(), StandardOpenOption.WRITE);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
파라미터 설명
batch_size 현재 반복자에서 next() 을 호출할 때마다 반환할 엔티티 수입니다.
기본값은 1000입니다. 적절한 값으로 설정하여 반복당 반환할 엔티티 수를 제어할 수 있습니다.
expr 일치하는 엔티티를 필터링하기 위한 스칼라 필터링 조건.
기본값은 없음으로, 스칼라 필터링이 무시됨을 나타냅니다. 스칼라 필터링 조건을 작성하려면 부울 표현식 규칙을 참조하세요.
output_fields 반환 시 각 엔티티에 포함할 필드 이름 목록.
기본값은 None입니다. 지정하지 않으면 기본 필드만 포함됩니다.
limit 반환할 총 엔티티 수.
기본값은 -1로, 일치하는 모든 엔티티가 반환됨을 나타냅니다.
매개변수 설명
withCollectionName 컬렉션 이름을 설정합니다. 컬렉션 이름은 비어 있거나 null일 수 없습니다.
withExpr 엔티티를 쿼리할 표현식을 설정합니다. 스칼라 필터링 조건을 작성하려면 부울 표현식 규칙을 참조하세요.
withBatchSize 현재 반복자에서 next() 을 호출할 때마다 반환할 엔티티 수.
기본값은 1000입니다. 적절한 값으로 설정하여 반복당 반환할 엔티티 수를 제어합니다.
addOutField 출력 스칼라 필드를 지정합니다(선택 사항).

번역DeepLogo

피드백

이 페이지가 도움이 되었나요?