mirror of
https://gitee.com/milvus-io/milvus.git
synced 2025-12-28 22:45:26 +08:00
issue: https://github.com/milvus-io/milvus/issues/27467 >My plan is as follows. >- [x] M1 Create collection with timestamptz field >- [x] M2 Insert timestamptz field data >- [x] M3 Retrieve timestamptz field data >- [x] M4 Implement handoff >- [x] M5 Implement compare operator >- [x] M6 Implement extract operator >- [x] M8 Support database/collection level default timezone >- [x] M7 Support STL-SORT index for datatype timestamptz --- The third PR of issue: https://github.com/milvus-io/milvus/issues/27467, which completes M5, M6, M7, M8 described above. ## M8 Default Timezone We will be able to use alter_collection() and alter_database() in a future Python SDK release to modify the default timezone at the collection or database level. For insert requests, the timezone will be resolved using the following order of precedence: String Literal-> Collection Default -> Database Default. For retrieval requests, the timezone will be resolved in this order: Query Parameters -> Collection Default -> Database Default. In both cases, the final fallback timezone is UTC. ## M5: Comparison Operators We can now use the following expression format to filter on the timestamptz field: - `timestamptz_field [+/- INTERVAL 'interval_string'] {comparison_op} ISO 'iso_string' ` - The interval_string follows the ISO 8601 duration format, for example: P1Y2M3DT1H2M3S. - The iso_string follows the ISO 8601 timestamp format, for example: 2025-01-03T00:00:00+08:00. - Example expressions: "tsz + INTERVAL 'P0D' != ISO '2025-01-03T00:00:00+08:00'" or "tsz != ISO '2025-01-03T00:00:00+08:00'". ## M6: Extract We will be able to extract sepecific time filed by kwargs in a future Python SDK release. The key is `time_fields`, and value should be one or more of "year, month, day, hour, minute, second, microsecond", seperated by comma or space. Then the result of each record would be an array of int64. ## M7: Indexing Support Expressions without interval arithmetic can be accelerated using an STL-SORT index. However, expressions that include interval arithmetic cannot be indexed. This is because the result of an interval calculation depends on the specific timestamp value. For example, adding one month to a date in February results in a different number of added days than adding one month to a date in March. --- After this PR, the input / output type of timestamptz would be iso string. Timestampz would be stored as timestamptz data, which is int64_t finally. > for more information, see https://en.wikipedia.org/wiki/ISO_8601 --------- Signed-off-by: xtx <xtianx@smail.nju.edu.cn>
Milvus Go Client Test Framework
Overview
This is a comprehensive test framework for the Milvus Go Client, designed to validate various functionalities of the Milvus vector database client. The framework provides a structured approach to writing tests with reusable components and helper functions.
Framework Architecture
Directory Structure
/go_client/
├── testcases/ # Main test cases
│ ├── helper/ # Helper functions and utilities
│ │ ├── helper.go
│ │ ├── data_helper.go
│ │ └── collection_helper.go
│ ├── search_test.go # Search functionality tests
│ ├── index_test.go # Index management tests
│ └── ...
├── common/ # Common utilities and constants
└── base/ # Base infrastructure code
Key Components
- Collection Preparation: Utilities for creating and managing collections
- Data Generation: Tools for generating test data
- Helper Functions: Common operations and validations
- Test Cases: Organized by functionality
Writing Test Cases
Basic Test Structure
func TestYourFeature(t *testing.T) {
// 1. Setup context and client
ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout)
mc := createDefaultMilvusClient(ctx, t)
// 2. Prepare collection
prepare, schema := hp.CollPrepare.CreateCollection(
ctx, t, mc,
hp.NewCreateCollectionParams(hp.Int64Vec),
hp.TNewFieldsOption(),
hp.TNewSchemaOption(),
)
// 3. Insert test data
prepare.InsertData(ctx, t, mc,
hp.NewInsertParams(schema),
hp.TNewDataOption(),
)
// 4. Execute test operations
// ... your test logic here ...
// 5. Validate results
require.NoError(t, err)
require.Equal(t, expected, actual)
}
Using Custom Parameters
- Collection Creation Parameters
fieldsOption := hp.TNewFieldsOption().
TWithEnableAnalyzer(true).
TWithAnalyzerParams(map[string]any{
"tokenizer": "standard",
})
schemaOption := hp.TNewSchemaOption().
TWithEnableDynamicField(true).
TWithDescription("Custom schema").
TWithAutoID(false)
- Data Insertion Options
insertOption := hp.TNewDataOption().
TWithNb(1000). // Number of records
TWithDim(128). // Vector dimension
TWithStart(100). // Starting ID
TWithMaxLen(256). // Maximum length
TWithTextLang("en") // Text language
- Index Parameters
indexParams := hp.TNewIndexParams(schema).
TWithFieldIndex(map[string]index.Index{
common.DefaultVectorFieldName: index.NewIVFSQIndex(
&index.IVFSQConfig{
MetricType: entity.L2,
NList: 128,
},
),
})
- Search Parameters
searchOpt := client.NewSearchOption(schema.CollectionName, 100, vectors).
WithOffset(0).
WithLimit(100).
WithConsistencyLevel(entity.ClStrong).
WithFilter("int64 >= 100").
WithOutputFields([]string{"*"}).
WithSearchParams(map[string]any{
"nprobe": 16,
"ef": 64,
})
Adding New Parameters
- Define New Option Type
// In helper/data_helper.go
type YourNewOption struct {
newParam1 string
newParam2 int
}
- Add Constructor
func TNewYourOption() *YourNewOption {
return &YourNewOption{
newParam1: "default",
newParam2: 0,
}
}
- Add Parameter Methods
func (opt *YourNewOption) TWithNewParam1(value string) *YourNewOption {
opt.newParam1 = value
return opt
}
func (opt *YourNewOption) TWithNewParam2(value int) *YourNewOption {
opt.newParam2 = value
return opt
}
Best Practices
-
Test Organization
- Group related tests in the same file
- Use clear and descriptive test names
- Add comments explaining test purpose
-
Data Generation
- Use helper functions for generating test data
- Ensure data is appropriate for the test case
- Clean up test data after use
-
Error Handling
- Use
common.CheckErrfor consistent error checking - Test both success and failure scenarios
- Validate error messages when appropriate
- Use
-
Performance Considerations
- Use appropriate timeouts
- Clean up resources after tests
- Consider test execution time
Running Tests
# Run all tests
go test ./testcases/...
# Run specific test
go test -run TestYourFeature ./testcases/
# Run with verbose output
go test -v ./testcases/...
# gotestsum
Recommend you to use gotestsum https://github.com/gotestyourself/gotestsum
# Run all default cases
gotestsum --format testname --hide-summary=output -v ./testcases/... --addr=127.0.0.1:19530 -timeout=30m
# Run a specified file
gotestsum --format testname --hide-summary=output ./testcases/collection_test.go ./testcases/main_test.go --addr=127.0.0.1:19530
# Run L3 rg cases
gotestsum --format testname --hide-summary=output -v ./testcases/advcases/... --addr=127.0.0.1:19530 -timeout=30m -tags=rg
# Run advanced rg cases and default cases
# rg cases conflicts with default cases, so -p=1 is required
gotestsum --format testname --hide-summary=output -v ./testcases/... --addr=127.0.0.1:19530 -timeout=30m -tags=rg -p 1
Contributing
- Follow the existing code structure
- Add comprehensive test cases
- Document new parameters and options
- Update this README for significant changes
- Ensure code quality standards:
- Run
golangci-lint runto check for style mistakes - Use
gofmt -w your/code/pathto format your code before submitting - CI will verify both golint and go format compliance
- Run