2
0

Format.ts 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. import {
  2. BYTE_UNITS,
  3. DEFAULT_MILVUS_PORT,
  4. DEFAULT_PROMETHEUS_PORT,
  5. VectorTypes,
  6. DataTypeStringEnum,
  7. DEFAULT_ANALYZER_PARAMS,
  8. DataTypeEnum,
  9. } from '@/consts';
  10. import {
  11. CreateFieldType,
  12. CreateField,
  13. } from '@/pages/databases/collections/Types';
  14. import { generateVector } from '.';
  15. import type { AnalyzerType } from '@/pages/databases/collections/Types';
  16. import type { FieldObject } from '@server/types';
  17. /**
  18. * transform large capacity to capacity in b.
  19. * @param capacity like: 10g, 10gb, 10m, 10mb, 10k, 10kb, 10b,
  20. * @return number
  21. */
  22. export const parseByte = (capacity?: string | number): number => {
  23. // if it's number return it
  24. if (!isNaN(Number(capacity))) {
  25. return capacity as number;
  26. }
  27. // capacity is '' or 0 or undefined
  28. if (!capacity) {
  29. return 0;
  30. }
  31. let lowerCapacity = (capacity as string).toLowerCase();
  32. const units = BYTE_UNITS;
  33. const isAlpha = /[a-zA-Z]/;
  34. const lastStr = lowerCapacity.charAt(lowerCapacity.length - 1);
  35. const secLastStr = lowerCapacity.charAt(lowerCapacity.length - 2);
  36. // if last two alpha is string, like: mb gb kb.
  37. // delete last alpha b
  38. if (isAlpha.test(lastStr) && isAlpha.test(secLastStr)) {
  39. lastStr === 'b' &&
  40. (lowerCapacity = lowerCapacity.slice(0, lowerCapacity.length - 1));
  41. }
  42. const suffix = lowerCapacity.charAt(lowerCapacity.length - 1);
  43. const digitsPart = lowerCapacity.slice(0, lowerCapacity.length - 1);
  44. if (units[suffix]) {
  45. return Number(digitsPart) * units[suffix];
  46. }
  47. throw new Error(
  48. 'The specified value for memory ({0}) should specify the units. The postfix should be one of the `b` `k` `m` `g` characters'
  49. );
  50. };
  51. /**
  52. *
  53. * @param search ?name=czz&age=18
  54. * @returns {name:'czz',age:'18'}
  55. */
  56. export const parseLocationSearch = (search: string) => {
  57. const pairs = search.substring(1).split('&');
  58. let obj: any = {};
  59. for (let i in pairs) {
  60. if (pairs[i] === '') continue;
  61. const pair = pairs[i].split('=');
  62. obj[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
  63. }
  64. return obj;
  65. };
  66. export const getEnumKeyByValue = (enumObj: any, enumValue: any) => {
  67. const match = Object.entries(enumObj).find(
  68. ([, value]) => value === enumValue
  69. );
  70. if (match) {
  71. const [key] = match;
  72. return key;
  73. }
  74. return '--';
  75. };
  76. /**
  77. * @param pairs e.g. [{key: 'key', value: 'value'}]
  78. * @returns object, e.g. {key: value}
  79. */
  80. export const getObjFromKeyValuePair = (
  81. pairs: { key: string; value: any }[]
  82. ): { [key in string]: any } => {
  83. const obj = pairs.reduce((acc, cur) => {
  84. acc[cur.key] = cur.value;
  85. return acc;
  86. }, {} as { [key in string]: any });
  87. return obj;
  88. };
  89. // BinarySubstructure includes Superstructure and Substructure
  90. export const checkIsBinarySubstructure = (metricLabel: string): boolean => {
  91. return metricLabel === 'Superstructure' || metricLabel === 'Substructure';
  92. };
  93. export const isVectorType = (field: FieldObject): boolean => {
  94. return VectorTypes.includes(field.dataType as any);
  95. };
  96. export const getCreateFieldType = (field: CreateField): CreateFieldType => {
  97. if (field.is_primary_key) {
  98. return 'primaryKey';
  99. }
  100. if (field.isDefault) {
  101. return 'defaultVector';
  102. }
  103. if (
  104. VectorTypes.includes(field.data_type) ||
  105. field.data_type === DataTypeEnum.VarCharBM25
  106. ) {
  107. return 'vector';
  108. }
  109. return 'number';
  110. };
  111. // Trim the address
  112. export const formatAddress = (address: string): string => {
  113. // remove http or https prefix from address
  114. const ip = address.replace(/(http):\/\//, '');
  115. return ip.includes(':') ? ip : `${ip}:${DEFAULT_MILVUS_PORT}`;
  116. };
  117. // format the prometheus address
  118. export const formatPrometheusAddress = (address: string): string => {
  119. let formatAddress = address;
  120. // add protocal (default http)
  121. const withProtocol = address.includes('http');
  122. if (!withProtocol) formatAddress = 'http://' + formatAddress;
  123. // add port (default 9090)
  124. const withPort = address.includes(':');
  125. if (!withPort) formatAddress = formatAddress + ':' + DEFAULT_PROMETHEUS_PORT;
  126. return formatAddress;
  127. };
  128. export const formatByteSize = (
  129. size: number,
  130. capacityTrans: { [key in string]: string }
  131. ) => {
  132. const power = Math.round(Math.log(size) / Math.log(1024));
  133. let unit = '';
  134. switch (power) {
  135. case 1:
  136. unit = capacityTrans.kb;
  137. break;
  138. case 2:
  139. unit = capacityTrans.mb;
  140. break;
  141. case 3:
  142. unit = capacityTrans.gb;
  143. break;
  144. case 4:
  145. unit = capacityTrans.tb;
  146. break;
  147. case 5:
  148. unit = capacityTrans.pb;
  149. break;
  150. default:
  151. unit = capacityTrans.b;
  152. break;
  153. }
  154. const byteValue = size / 1024 ** power;
  155. return {
  156. value: byteValue.toFixed(2),
  157. unit,
  158. power,
  159. originValue: size,
  160. };
  161. };
  162. // generate a sting like 20.22/98.33MB with proper unit
  163. export const getByteString = (
  164. value1: number,
  165. value2: number,
  166. capacityTrans: { [key in string]: string }
  167. ) => {
  168. if (!value1 || !value2) return `0${capacityTrans.b}`;
  169. const formatValue1 = formatByteSize(value1, capacityTrans);
  170. const formatValue2 = value2 / 1024 ** formatValue1.power;
  171. return `${formatValue1.value}/${formatValue2.toFixed(2)} ${
  172. formatValue1.unit
  173. }`;
  174. };
  175. /**
  176. * time: 2022-02-15 07:03:32.2981238 +0000 UTC m=+2.434915801
  177. * @returns 2022-02-15 07:03:32
  178. */
  179. export const formatSystemTime = (time: string): string => {
  180. return time.split('.')[0] || '';
  181. };
  182. /**
  183. * When number is larger than js max number, transform to string by BigInt.
  184. * @param bigNumber
  185. * @returns
  186. */
  187. export const formatUtcToMilvus = (bigNumber: number) => {
  188. const milvusTimeStamp = BigInt(bigNumber) << BigInt(18);
  189. return milvusTimeStamp.toString();
  190. };
  191. /**
  192. * Format field
  193. * @param bigNumber
  194. * @returns
  195. */
  196. export const formatFieldType = (field: FieldObject) => {
  197. const { name, data_type, element_type, maxLength, maxCapacity, dimension } =
  198. field;
  199. if (name === '$meta') {
  200. return `${data_type}`;
  201. }
  202. const elementType =
  203. element_type !== 'None'
  204. ? `<${element_type}${maxLength !== -1 ? `(${maxLength})` : ''}>`
  205. : '';
  206. const maxCap = maxCapacity !== -1 ? `[${maxCapacity}]` : '';
  207. const dim = dimension !== -1 ? `(${dimension})` : '';
  208. const maxLn = data_type === 'VarChar' ? `(${maxLength})` : '';
  209. return `${data_type}${elementType}${maxCap}${dim}${maxLn}`;
  210. };
  211. export const isSparseVector = (str: string): boolean => {
  212. try {
  213. str = str.trim();
  214. if (str === '') return false;
  215. if (str[0] !== '{' || str[str.length - 1] !== '}') return false;
  216. const innerStr = str.slice(1, -1);
  217. const pairs = innerStr.split(',');
  218. for (const pair of pairs) {
  219. const [key, value] = pair.split(':');
  220. const trimmedKey = key && key.trim();
  221. const trimmedValue = value && value.trim();
  222. if (
  223. !(
  224. (trimmedKey.match(/^".*"$/) && trimmedKey.length > 2) ||
  225. trimmedKey.match(/^\d+$/)
  226. ) ||
  227. !trimmedValue.match(/^(\d*\.)?\d+$/)
  228. ) {
  229. return false;
  230. }
  231. }
  232. return true;
  233. } catch (error) {
  234. return false;
  235. }
  236. };
  237. // transform ObjStr To JSONStr
  238. // `{a: 1, b: 2}` => `{"a": 1, "b": 2}`
  239. // `{'a': 1, 'b': 2}` => `{"a": 1, "b": 2}`
  240. // `{'a': 1, b: 2}` => `{"a": 1, "b": 2}`
  241. // it may have empty space between key and value
  242. export const transformObjStrToJSONStr = (str: string): string => {
  243. const objStr = str.replace(/'/g, '"').replace(/(\w+)\s*:/g, '"$1":');
  244. return objStr;
  245. };
  246. // transform object to valid string without quotes
  247. // {a: 1, b: 2} => '{a: 1, b: 2}'
  248. export const transformObjToStr = (obj: any): string => {
  249. const str = JSON.stringify(obj);
  250. return str.replace(/"/g, '');
  251. };
  252. export const generateVectorsByField = (field: FieldObject) => {
  253. switch (field.data_type) {
  254. case DataTypeStringEnum.FloatVector:
  255. case DataTypeStringEnum.BinaryVector:
  256. case DataTypeStringEnum.Float16Vector:
  257. case DataTypeStringEnum.BFloat16Vector:
  258. const dim =
  259. field.data_type === DataTypeStringEnum.BinaryVector
  260. ? field.dimension / 8
  261. : field.dimension;
  262. return JSON.stringify(generateVector(dim));
  263. case DataTypeStringEnum.SparseFloatVector:
  264. return field.is_function_output
  265. ? 'fox'
  266. : transformObjToStr({
  267. [Math.floor(Math.random() * 10)]: Math.random(),
  268. });
  269. default:
  270. return [1, 2, 3];
  271. }
  272. };
  273. const arrayFormatter = (value: string) => {
  274. return JSON.parse(value);
  275. };
  276. const sparseVectorFormatter = (str: string) => {
  277. return JSON.parse(transformObjStrToJSONStr(str));
  278. };
  279. export const VectorStrToObject = {
  280. [DataTypeStringEnum.FloatVector]: arrayFormatter,
  281. [DataTypeStringEnum.BinaryVector]: arrayFormatter,
  282. [DataTypeStringEnum.Float16Vector]: arrayFormatter,
  283. [DataTypeStringEnum.BFloat16Vector]: arrayFormatter,
  284. [DataTypeStringEnum.SparseFloatVector]: sparseVectorFormatter,
  285. };
  286. export const getColumnWidth = (field: FieldObject): number => {
  287. switch (field.data_type) {
  288. case DataTypeStringEnum.Int64:
  289. case DataTypeStringEnum.Int32:
  290. case DataTypeStringEnum.Int16:
  291. case DataTypeStringEnum.Int8:
  292. return 200;
  293. case DataTypeStringEnum.Float:
  294. return 200;
  295. case DataTypeStringEnum.VarChar:
  296. const varCharWidth = field.maxLength * 10;
  297. return varCharWidth > 350 ? 350 : varCharWidth;
  298. case DataTypeStringEnum.Bool:
  299. return 80;
  300. case DataTypeStringEnum.Array:
  301. const width =
  302. getColumnWidth({
  303. ...field,
  304. data_type: field.element_type as any,
  305. }) * field.maxCapacity;
  306. return width > 350 ? 350 : width;
  307. default:
  308. return 350;
  309. }
  310. };
  311. export const getAnalyzerParams = (
  312. analyzerParams: AnalyzerType | Record<AnalyzerType, any>
  313. ): Record<string, any> => {
  314. if (typeof analyzerParams === 'string') {
  315. return DEFAULT_ANALYZER_PARAMS[analyzerParams as AnalyzerType];
  316. }
  317. return analyzerParams;
  318. };