// Licensed to the LF AI & Data foundation under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package milvusclient import ( "fmt" "github.com/milvus-io/milvus-proto/go-api/v2/milvuspb" "github.com/milvus-io/milvus/client/v2/entity" "github.com/milvus-io/milvus/client/v2/index" ) type SearchIteratorOption interface { // SearchOption returns the search option when iterate search SearchOption() *searchOption // Limit returns the overall limit of entries to iterate Limit() int64 // ValidateParams performs the static params validation ValidateParams() error } type searchIteratorOption struct { *searchOption batchSize int iteratorLimit int64 } func (opt *searchIteratorOption) SearchOption() *searchOption { opt.annRequest.topK = opt.batchSize opt.WithSearchParam(IteratorSearchBatchSizeKey, fmt.Sprintf("%d", opt.batchSize)) return opt.searchOption } func (opt *searchIteratorOption) Limit() int64 { return opt.iteratorLimit } // ValidateParams performs the static params validation func (opt *searchIteratorOption) ValidateParams() error { if opt.batchSize <= 0 { return fmt.Errorf("batch size must be greater than 0") } return nil } func (opt *searchIteratorOption) WithBatchSize(batchSize int) *searchIteratorOption { opt.batchSize = batchSize return opt } func (opt *searchIteratorOption) WithPartitions(partitionNames ...string) *searchIteratorOption { opt.partitionNames = partitionNames return opt } func (opt *searchIteratorOption) WithFilter(expr string) *searchIteratorOption { opt.annRequest.WithFilter(expr) return opt } func (opt *searchIteratorOption) WithTemplateParam(key string, val any) *searchIteratorOption { opt.annRequest.WithTemplateParam(key, val) return opt } func (opt *searchIteratorOption) WithOffset(offset int) *searchIteratorOption { opt.annRequest.WithOffset(offset) return opt } func (opt *searchIteratorOption) WithOutputFields(fieldNames ...string) *searchIteratorOption { opt.outputFields = fieldNames return opt } func (opt *searchIteratorOption) WithConsistencyLevel(consistencyLevel entity.ConsistencyLevel) *searchIteratorOption { opt.consistencyLevel = consistencyLevel opt.useDefaultConsistencyLevel = false return opt } func (opt *searchIteratorOption) WithANNSField(annsField string) *searchIteratorOption { opt.annRequest.WithANNSField(annsField) return opt } func (opt *searchIteratorOption) WithGroupByField(groupByField string) *searchIteratorOption { opt.annRequest.WithGroupByField(groupByField) return opt } func (opt *searchIteratorOption) WithGroupSize(groupSize int) *searchIteratorOption { opt.annRequest.WithGroupSize(groupSize) return opt } func (opt *searchIteratorOption) WithStrictGroupSize(strictGroupSize bool) *searchIteratorOption { opt.annRequest.WithStrictGroupSize(strictGroupSize) return opt } func (opt *searchIteratorOption) WithIgnoreGrowing(ignoreGrowing bool) *searchIteratorOption { opt.annRequest.WithIgnoreGrowing(ignoreGrowing) return opt } func (opt *searchIteratorOption) WithAnnParam(ap index.AnnParam) *searchIteratorOption { opt.annRequest.WithAnnParam(ap) return opt } func (opt *searchIteratorOption) WithSearchParam(key, value string) *searchIteratorOption { opt.annRequest.WithSearchParam(key, value) return opt } // WithIteratorLimit sets the limit of entries to iterate // if limit < 0, then it will be set to Unlimited func (opt *searchIteratorOption) WithIteratorLimit(limit int64) *searchIteratorOption { if limit < 0 { limit = Unlimited } opt.iteratorLimit = limit return opt } func NewSearchIteratorOption(collectionName string, vector entity.Vector) *searchIteratorOption { return &searchIteratorOption{ searchOption: NewSearchOption(collectionName, 1000, []entity.Vector{vector}). WithSearchParam(IteratorKey, "true"). WithSearchParam(IteratorSearchV2Key, "true"), batchSize: 1000, iteratorLimit: Unlimited, } } // QueryIteratorOption is the interface for query iterator options. type QueryIteratorOption interface { // Request returns the query request when iterate query Request() (*milvuspb.QueryRequest, error) // BatchSize returns the batch size for each query iteration BatchSize() int // Limit returns the overall limit of entries to iterate Limit() int64 // ValidateParams performs the static params validation ValidateParams() error } type queryIteratorOption struct { collectionName string partitionNames []string outputFields []string expr string batchSize int iteratorLimit int64 consistencyLevel entity.ConsistencyLevel useDefaultConsistencyLevel bool } func (opt *queryIteratorOption) Request() (*milvuspb.QueryRequest, error) { return &milvuspb.QueryRequest{ CollectionName: opt.collectionName, PartitionNames: opt.partitionNames, OutputFields: opt.outputFields, Expr: opt.expr, ConsistencyLevel: opt.consistencyLevel.CommonConsistencyLevel(), UseDefaultConsistency: opt.useDefaultConsistencyLevel, QueryParams: entity.MapKvPairs(map[string]string{IteratorKey: "true", "reduce_stop_for_best": "true"}), }, nil } func (opt *queryIteratorOption) BatchSize() int { return opt.batchSize } func (opt *queryIteratorOption) Limit() int64 { return opt.iteratorLimit } func (opt *queryIteratorOption) ValidateParams() error { if opt.batchSize <= 0 { return fmt.Errorf("batch size must be greater than 0") } return nil } func (opt *queryIteratorOption) WithBatchSize(batchSize int) *queryIteratorOption { opt.batchSize = batchSize return opt } func (opt *queryIteratorOption) WithPartitions(partitionNames ...string) *queryIteratorOption { opt.partitionNames = partitionNames return opt } func (opt *queryIteratorOption) WithFilter(expr string) *queryIteratorOption { opt.expr = expr return opt } func (opt *queryIteratorOption) WithOutputFields(fieldNames ...string) *queryIteratorOption { opt.outputFields = fieldNames return opt } func (opt *queryIteratorOption) WithConsistencyLevel(consistencyLevel entity.ConsistencyLevel) *queryIteratorOption { opt.consistencyLevel = consistencyLevel opt.useDefaultConsistencyLevel = false return opt } // WithIteratorLimit sets the limit of entries to iterate // if limit < 0, then it will be set to Unlimited func (opt *queryIteratorOption) WithIteratorLimit(limit int64) *queryIteratorOption { if limit < 0 { limit = Unlimited } opt.iteratorLimit = limit return opt } func NewQueryIteratorOption(collectionName string) *queryIteratorOption { return &queryIteratorOption{ collectionName: collectionName, batchSize: 1000, iteratorLimit: Unlimited, useDefaultConsistencyLevel: true, consistencyLevel: entity.ClBounded, } }