Skip to content

Commit

Permalink
[2.5] support default value and null (#369)
Browse files Browse the repository at this point in the history
* init 2.5

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* update milvus version

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* update proto

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* WIP: support default value & null

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* fix json format

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* WIP

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* WIP

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* WIP

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* add null test for array

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* recover ip

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* WIP

Signed-off-by: shanghaikid <jiangruiyi@gmail.com>

* finish default_null

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* update test version

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* fix test

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* update test

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

---------

Signed-off-by: ryjiang <jiangruiyi@gmail.com>
Signed-off-by: shanghaikid <jiangruiyi@gmail.com>
  • Loading branch information
shanghaikid authored Nov 6, 2024
1 parent f546023 commit 9f46da2
Show file tree
Hide file tree
Showing 20 changed files with 255 additions and 81 deletions.
13 changes: 9 additions & 4 deletions milvus/grpc/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
CreateCollectionWithFieldsReq,
CreateCollectionWithSchemaReq,
FieldSchema,
isVectorType,
} from '../';

/**
Expand Down Expand Up @@ -1054,9 +1055,12 @@ export class Collection extends Database {
* });
* ```
*/
async getPkFieldName(data: DescribeCollectionReq): Promise<string> {
async getPkFieldName(
data: DescribeCollectionReq,
desc?: DescribeCollectionResponse
): Promise<string> {
// get collection info
const collectionInfo = await this.describeCollection(data);
const collectionInfo = desc ? desc : await this.describeCollection(data);

// pk field
let pkField = '';
Expand Down Expand Up @@ -1094,10 +1098,11 @@ export class Collection extends Database {
* ```
*/
async getPkFieldType(
data: DescribeCollectionReq
data: DescribeCollectionReq,
desc?: DescribeCollectionResponse
): Promise<keyof typeof DataType> {
// get collection info
const collectionInfo = await this.describeCollection(data);
const collectionInfo = desc ? desc : await this.describeCollection(data);

// pk field type
let pkFieldType: keyof typeof DataType = 'Int64';
Expand Down
40 changes: 29 additions & 11 deletions milvus/grpc/Data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
buildDynamicRow,
buildFieldDataMap,
getDataKey,
Field,
_Field,
buildFieldData,
BinaryVector,
RowData,
Expand All @@ -65,6 +65,7 @@ import {
sparseRowsToBytes,
getSparseDim,
f32ArrayToBinaryBytes,
getValidDataArray,
NO_LIMIT,
} from '../';
import { Collection } from './Collection';
Expand Down Expand Up @@ -143,7 +144,7 @@ export class Data extends Collection {
// Tip: The field data sequence needs to be set same as `collectionInfo.schema.fields`.
// If primarykey is set `autoid = true`, you cannot insert the data.
// and if function field is set, you need to ignore the field value in the data.
const fieldMap = new Map<string, Field>(
const fieldMap = new Map<string, _Field>(
collectionInfo.schema.fields
.filter(v => !v.is_primary_key || !v.autoID)
.filter(v => !v.is_function_output)
Expand All @@ -155,6 +156,8 @@ export class Data extends Collection {
elementType: v.element_type,
dim: Number(findKeyValue(v.type_params, 'dim')),
data: [], // values container
nullable: v.nullable,
default_value: v.default_value,
},
])
);
Expand All @@ -167,6 +170,7 @@ export class Data extends Collection {
type: 'JSON',
elementType: 'None',
data: [], // value container
nullable: false,
});
}

Expand Down Expand Up @@ -225,6 +229,10 @@ export class Data extends Collection {
const dataKey = getDataKey(type);
const elementType = DataTypeMap[field.elementType!];
const elementTypeKey = getDataKey(elementType);
const valid_data = getValidDataArray(
field.data,
data.fields_data?.length!
);

// build key value
let keyValue;
Expand Down Expand Up @@ -263,32 +271,41 @@ export class Data extends Collection {
case DataType.Array:
keyValue = {
[dataKey]: {
data: field.data.map(d => {
return {
[elementTypeKey]: {
type: elementType,
data: d,
},
};
}),
data: field.data
.filter(v => v !== undefined)
.map(d => {
return {
[elementTypeKey]: {
type: elementType,
data: d,
},
};
}),
element_type: elementType,
},
};
break;
default:
keyValue = {
[dataKey]: {
data: field.data,
data: field.data.filter(v => v !== undefined),
},
};
break;
}

const needValidData =
key !== 'vectors' &&
(field.nullable === true ||
(typeof field.default_value !== 'undefined' &&
field.default_value !== null));

return {
type,
field_name: field.name,
is_dynamic: field.name === DEFAULT_DYNAMIC_FIELD,
[key]: keyValue,
valid_data: needValidData ? valid_data : [],
};
});

Expand Down Expand Up @@ -931,6 +948,7 @@ export class Data extends Collection {
// always get output_fields from fields_data
const output_fields = promise.fields_data.map(f => f.field_name);

// build field data map
const fieldsDataMap = buildFieldDataMap(
promise.fields_data,
data.transformers
Expand Down
9 changes: 5 additions & 4 deletions milvus/types/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ export interface FieldSchema {
element_type?: keyof typeof DataType;
default_value?: number | string;
dataType: DataType;
is_partition_key: boolean;
is_dynamic: boolean;
is_clustering_key: boolean;
is_partition_key?: boolean;
is_dynamic?: boolean;
is_clustering_key?: boolean;
nullable?: boolean;
is_function_output: boolean;
nullable: boolean;
}

export interface CollectionData {
Expand Down Expand Up @@ -80,6 +80,7 @@ export interface FieldType {
max_capacity?: TypeParam;
max_length?: TypeParam;
default_value?: number | string;
nullable?: boolean;
enable_match?: boolean;
tokenizer_params?: Record<string, any>;
enable_tokenizer?: boolean;
Expand Down
9 changes: 7 additions & 2 deletions milvus/types/Data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,22 @@ export type FieldData =
| VarChar
| JSON
| Array
| VectorTypes;
| VectorTypes
| null;

// Represents a row of data in Milvus.
export interface RowData {
[x: string]: FieldData;
}

export interface Field {
export interface _Field {
name: string;
type: keyof typeof DataType;
elementType?: keyof typeof DataType;
data: FieldData[];
dim?: number;
nullable?: boolean;
default_value?: FieldData;
}

export interface FlushReq extends GrpcTimeOut {
Expand Down Expand Up @@ -455,6 +458,8 @@ export interface QueryRes extends resStatusResponse {
[x: string]: any;
data: string;
};
is_dynamic: boolean;
valid_data: boolean[];
}[];
output_fields: string[];
collection_name: string;
Expand Down
26 changes: 19 additions & 7 deletions milvus/utils/Format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
DescribeCollectionResponse,
getDataKey,
RowData,
Field,
_Field,
JSON,
FieldData,
CreateCollectionWithFieldsReq,
Expand Down Expand Up @@ -421,7 +421,7 @@ export const formatDescribedCol = (
*/
export const buildDynamicRow = (
rowData: RowData,
fieldMap: Map<string, Field>,
fieldMap: Map<string, _Field>,
dynamicFieldName: string
) => {
const originRow = cloneObj(rowData);
Expand Down Expand Up @@ -537,17 +537,27 @@ export const buildFieldDataMap = (
});
}

// decode json
switch (dataKey) {
// decode json
case 'json_data':
field_data.forEach((buffer: any, i: number) => {
// console.log(JSON.parse(buffer.toString()));
field_data[i] = JSON.parse(buffer.toString());
field_data[i] = buffer.length
? JSON.parse(buffer.toString())
: null;
});
break;
default:
break;
}

// set the field data with null if item.valid_data is not empty array, it the item in valid_data is false, set the field data with null
if (item.valid_data && item.valid_data.length) {
item.valid_data.forEach((v: any, i: number) => {
if (!v) {
field_data[i] = null;
}
});
}
}

// Add the parsed data to the fieldsDataMap
Expand Down Expand Up @@ -591,7 +601,7 @@ export const getAuthString = (data: {
*/
export const buildFieldData = (
rowData: RowData,
field: Field,
field: _Field,
transformers?: InsertTransformers
): FieldData => {
const { type, elementType, name } = field;
Expand All @@ -614,7 +624,9 @@ export const buildFieldData = (
? f16Transformer(rowData[name] as Float16Vector)
: rowData[name];
case DataType.JSON:
return Buffer.from(JSON.stringify(rowData[name] || {}));
return rowData[name]
? Buffer.from(JSON.stringify(rowData[name] || {}))
: Buffer.alloc(0);
case DataType.Array:
const elementField = { ...field, type: elementType! };
return buildFieldData(rowData, elementField, transformers);
Expand Down
9 changes: 9 additions & 0 deletions milvus/utils/Function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
DEFAULT_MIN_INT64,
SearchResultData,
SparseFloatVector,
FieldData,
} from '../';
import { Pool } from 'generic-pool';

Expand Down Expand Up @@ -236,3 +237,11 @@ export const getSparseDim = (data: SparseFloatVector[]) => {
}
return dim;
};

// get valid data
// create a length array with valid data, if the data is undefined or null, return false, otherwise return true
export const getValidDataArray = (data: FieldData[], length: number) => {
return Array.from({ length }).map((_, i) => {
return data[i] !== undefined && data[i] !== null;
});
};
4 changes: 2 additions & 2 deletions milvus/utils/Grpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export const getRetryInterceptor = ({
logger.debug(
`\x1b[32m[Response(${
Date.now() - startTime.getTime()
}ms)]\x1b[0m\x1b[2m${clientId}\x1b[0m>${dbname}>\x1b[1m${methodName}\x1b[0m: ${string}`
}ms)]\x1b[0m\x1b[2m${clientId}\x1b[0m>${dbname}>\x1b[1m${methodName}\x1b[0m: ${msg}`
);

savedMessageNext(savedReceiveMessage);
Expand All @@ -217,7 +217,7 @@ export const getRetryInterceptor = ({
const msg =
string.length > 2048 ? string.slice(0, 2048) + '...' : string;
logger.debug(
`\x1b[34m[Request]\x1b[0m${clientId}>${dbname}>\x1b[1m${methodName}(${timeoutInSeconds})\x1b[0m: ${string}`
`\x1b[34m[Request]\x1b[0m${clientId}>${dbname}>\x1b[1m${methodName}(${timeoutInSeconds})\x1b[0m: ${msg}`
);
savedSendMessage = message;
next(message);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zilliz/milvus2-sdk-node",
"author": "ued@zilliz.com",
"milvusVersion": "master-20241024-f78f6112-amd64",
"milvusVersion": "master-20241105-bd04cac4-amd64",
"version": "2.4.9",
"main": "dist/milvus",
"files": [
Expand Down
2 changes: 1 addition & 1 deletion proto
6 changes: 5 additions & 1 deletion test/build/Collection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ describe('Collection Api', () => {

try {
await milvusClient.createCollection(
genCollectionParams({ collectionName: 'any', dim: [8] })
genCollectionParams({
collectionName: 'any',
vectorType: [DataType.BinaryVector],
dim: [6],
})
);
} catch (error) {
expect(error.message).toEqual(
Expand Down
Loading

0 comments on commit 9f46da2

Please sign in to comment.