UNPKG

@zilliz/milvus2-sdk-node

Version:

Official Node.js SDK for [Milvus](https://github.com/milvus-io/milvus) vector database. Provides gRPC and HTTP clients for vector similarity search, metadata filtering, and full collection/index/user management.

316 lines • 14.4 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatCollectionSchema = exports.formatStructArrayFieldSchema = exports.formatFunctionSchema = exports.formatFieldSchema = exports.convertToDataType = exports.assignTypeParams = exports.getDataKey = exports.buildDefaultSchema = void 0; const __1 = require("../"); function convertToCamelCase(str) { return str.replace(/_(.)/g, function (match, letter) { return letter.toUpperCase(); }); } // build default schema const buildDefaultSchema = (data) => { return [ { name: data.primary_field_name, data_type: data.id_type, is_primary_key: true, autoID: data.auto_id, }, { name: data.vector_field_name, data_type: __1.DataType.FloatVector, dim: data.dimension, }, ]; }; exports.buildDefaultSchema = buildDefaultSchema; const getDataKey = (type, camelCase = false) => { let dataKey = ''; switch (type) { case __1.DataType.FloatVector: dataKey = 'float_vector'; break; case __1.DataType.Float16Vector: dataKey = 'float16_vector'; break; case __1.DataType.BFloat16Vector: dataKey = 'bfloat16_vector'; break; case __1.DataType.BinaryVector: dataKey = 'binary_vector'; break; case __1.DataType.SparseFloatVector: dataKey = 'sparse_float_vector'; break; case __1.DataType.Int8Vector: dataKey = 'int8_vector'; break; case __1.DataType.Double: dataKey = 'double_data'; break; case __1.DataType.Float: dataKey = 'float_data'; break; case __1.DataType.Int64: dataKey = 'long_data'; break; case __1.DataType.Int32: case __1.DataType.Int16: case __1.DataType.Int8: dataKey = 'int_data'; break; case __1.DataType.Bool: dataKey = 'bool_data'; break; case __1.DataType.VarChar: case __1.DataType.Text: dataKey = 'string_data'; break; case __1.DataType.Array: dataKey = 'array_data'; break; case __1.DataType.JSON: dataKey = 'json_data'; break; case __1.DataType.Geometry: dataKey = 'geometry_wkt_data'; break; case __1.DataType.Timestamptz: dataKey = 'timestamptz_data'; break; case __1.DataType.ArrayOfVector: dataKey = 'vector_array'; break; case __1.DataType.None: case __1.DataType.Struct: dataKey = 'none'; break; default: throw new Error(`${__1.ERROR_REASONS.INSERT_CHECK_WRONG_DATA_TYPE} "${type}."`); } return camelCase ? convertToCamelCase(dataKey) : dataKey; }; exports.getDataKey = getDataKey; const normalizeFunctionType = (type) => { var _a, _b; if (typeof type !== 'string') { return type; } return ((_b = (_a = __1.FunctionType[type]) !== null && _a !== void 0 ? _a : __1.FunctionType[type.toUpperCase()]) !== null && _b !== void 0 ? _b : type); }; /** * Assigns specified properties from the `field` object to `type_params` within the `FieldType` object. * Converts properties to strings, serializing objects as JSON strings if needed, then removes them from `field`. * * @param field - The `FieldType` object to modify. * @param typeParamKeys - Keys to assign to `type_params` if present in `field`. * @returns The modified `FieldType` object. */ const assignTypeParams = (field, typeParamKeys = [ 'dim', 'max_length', 'max_capacity', 'enable_match', 'enable_analyzer', 'analyzer_params', 'multi_analyzer_params', 'mmap.enabled', ]) => { var _a; const newField = (0, __1.cloneObj)(field); // Initialize `type_params` if undefined (_a = newField.type_params) !== null && _a !== void 0 ? _a : (newField.type_params = {}); typeParamKeys.forEach(key => { if (key in newField) { const value = newField[key]; // Convert the value to a string, JSON-stringify if it's an object newField.type_params[key] = typeof value === 'object' ? JSON.stringify(value) : String(value !== null && value !== void 0 ? value : ''); delete newField[key]; } }); // delete type_params if it's empty if (!Object.keys(newField.type_params).length) { delete newField.type_params; } return newField; }; exports.assignTypeParams = assignTypeParams; /** * Converts a `key` of type `keyof typeof DataTypeMap | DataType` to a `DataType`. * * @param {keyof typeof DataTypeMap | DataType} key - The key to convert. * @returns {DataType} The converted `DataType`. */ const convertToDataType = (key) => { if (typeof key === 'string' && key in __1.DataTypeMap) { return __1.DataType[key]; } else if (typeof key === 'number' && Object.values(__1.DataType).includes(key)) { return key; } else if (typeof key === 'number') { return key; // for internal data type like ArrayOfVector 106 } throw new Error(__1.ERROR_REASONS.FIELD_TYPE_IS_NOT_SUPPORT); }; exports.convertToDataType = convertToDataType; /** * Formats a field schema by converting its properties to the appropriate types and adding additional properties. * * @param {FieldType} field - The field to format. * @param {Record<string, Type>} schemaTypes - The schema types to use for formatting. * @param {Object} [override] - Optional override object for additional properties. * @returns {Object} The formatted field schema. */ const formatFieldSchema = (field, schemaTypes, override) => { const { partition_key_field, functionOutputFields = [], clustering_key_field, } = override || {}; // Assign the typeParams property to the result of parseToKeyValue(type_params). const _a = (0, exports.assignTypeParams)(field), { type_params, data_type, element_type, is_function_output, is_partition_key, is_primary_key, external_field } = _a, rest = __rest(_a, ["type_params", "data_type", "element_type", "is_function_output", "is_partition_key", "is_primary_key", "external_field"]); const dataType = (0, exports.convertToDataType)(field.data_type); const createObj = Object.assign(Object.assign({}, rest), { typeParams: (0, __1.parseToKeyValue)(type_params), data_type, dataType, isPrimaryKey: !!is_primary_key, isPartitionKey: !!is_partition_key || field.name === partition_key_field, isFunctionOutput: !!is_function_output || functionOutputFields.includes(field.name), isClusteringKey: !!field.is_clustering_key || field.name === clustering_key_field }); if (external_field) { createObj.externalField = external_field; } // if element type exist and if ((dataType === __1.DataType.Array || dataType === __1.DataType.ArrayOfVector) && typeof element_type !== 'undefined') { createObj.elementType = (0, exports.convertToDataType)(element_type); createObj.element_type = element_type; // compatibility with old version } if (typeof field.default_value !== 'undefined') { const dataKey = (0, exports.getDataKey)(createObj.dataType, true); let defaultValue = field.default_value; // Convert TIMESTAMPTZ default value to UTC microseconds (int64) // Milvus stores TIMESTAMPTZ default values internally as int64 (UTC microsecond) // Users can pass either a string (RFC3339 format) or a number (microseconds) if (createObj.dataType === __1.DataType.Timestamptz) { if (typeof defaultValue === 'string') { // Convert RFC3339 string to UTC microseconds const date = new Date(defaultValue); defaultValue = (date.getTime() * 1000).toString(); } else if (typeof defaultValue === 'number') { // If already a number, assume it's microseconds (or milliseconds if < 1e12) // Convert to microseconds if it looks like milliseconds (< year 2286) const value = defaultValue < 1e12 ? defaultValue * 1000 : defaultValue; defaultValue = Math.floor(value).toString(); } } createObj.defaultValue = { [dataKey]: defaultValue, }; } return schemaTypes.fieldSchemaType.create(createObj); }; exports.formatFieldSchema = formatFieldSchema; /** * Formats a FunctionObject into a FunctionSchema payload for gRPC. * Returns a plain object with snake_case field names matching the proto definition * in milvus.ts (used by @grpc/proto-loader). * * @param {FunctionObject} func - The function object to format. * @returns {Object} The formatted function schema payload (plain object). */ const formatFunctionSchema = (func) => { const { input_field_names, output_field_names, type } = func, rest = __rest(func, ["input_field_names", "output_field_names", "type"]); // Return a plain object with snake_case field names for gRPC // The @grpc/proto-loader uses milvus.ts which has snake_case field names return Object.assign(Object.assign({}, rest), { type: normalizeFunctionType(type), input_field_names: input_field_names || [], output_field_names: output_field_names || [], params: (0, __1.parseToKeyValue)(func.params, true) }); }; exports.formatFunctionSchema = formatFunctionSchema; /** * Formats a struct array field schema by converting its properties to the appropriate types and adding additional properties. * * @param {FieldType} field - The field to format. * @param {Record<string, Type>} schemaTypes - The schema types to use for formatting. * @returns {Object} The formatted struct array field schema. */ const formatStructArrayFieldSchema = (field, schemaTypes) => { var _a, _b; const formattedField = (0, exports.assignTypeParams)(field); const structTypeParams = Object.assign({}, formattedField.type_params); delete structTypeParams.max_capacity; const maxCapacity = (_a = field.max_capacity) !== null && _a !== void 0 ? _a : (_b = field.type_params) === null || _b === void 0 ? void 0 : _b.max_capacity; return schemaTypes.structArrayFieldSchemaType.create({ name: field.name, description: field.description, nullable: field.nullable === true, typeParams: (0, __1.parseToKeyValue)(structTypeParams), fields: field.fields.map((f) => { const childDataType = (0, exports.convertToDataType)(f.data_type); const childField = Object.assign(Object.assign({}, f), { element_type: childDataType, data_type: (0, __1.isVectorType)(childDataType) ? __1.DataType.ArrayOfVector : __1.DataType.Array, max_capacity: maxCapacity, nullable: field.nullable === true }); // format schema return (0, exports.formatFieldSchema)(childField, schemaTypes); }), }); }; exports.formatStructArrayFieldSchema = formatStructArrayFieldSchema; /** * Formats the input data into a request payload for creating a collection. * * @param {CreateCollectionReq} data - The input data for creating a collection. * @param {Type} schemaType - The schema type for the collection. * @returns {Object} The formatted request payload. */ const formatCollectionSchema = (data, schemaTypes) => { const { collection_name, description, enable_dynamic_field, enableDynamicField, partition_key_field, functions, clustering_key_field, external_source, external_spec, file_resource_ids, } = data; let fields = data.fields; if (data.schema) { fields = data.schema; } let payload = {}; // extract function output fields const functionOutputFields = []; // if functions is set, parse its params to key-value pairs, and delete inputs and outputs if (functions) { payload.functions = functions.map((func) => { const { input_field_names, output_field_names, type } = func, rest = __rest(func, ["input_field_names", "output_field_names", "type"]); functionOutputFields.push(...(output_field_names || [])); return schemaTypes.functionSchemaType.create(Object.assign(Object.assign({}, rest), { type: normalizeFunctionType(type), inputFieldNames: input_field_names || [], outputFieldNames: output_field_names || [], params: (0, __1.parseToKeyValue)(func.params, true) })); }); } // extract struct array fields and others const [structArrayFields, fieldsWithoutStructArray] = fields.reduce((acc, field) => { if (field.data_type === __1.DataType.Array && field.element_type === __1.DataType.Struct) { acc[0].push(field); } else { acc[1].push(field); } return acc; }, [[], []]); // format the payload payload = Object.assign({ name: collection_name, description: description || '', enableDynamicField: !!enableDynamicField || !!enable_dynamic_field, fields: fieldsWithoutStructArray.map(field => (0, exports.formatFieldSchema)(field, schemaTypes, { partition_key_field, functionOutputFields, clustering_key_field, })), structArrayFields: structArrayFields.map(field => (0, exports.formatStructArrayFieldSchema)(field, schemaTypes)) }, payload); if (external_source) { payload.externalSource = external_source; } if (external_spec) { payload.externalSpec = external_spec; } if (file_resource_ids) { payload.fileResourceIds = file_resource_ids; } return payload; }; exports.formatCollectionSchema = formatCollectionSchema; //# sourceMappingURL=Schema.js.map