collections.controller.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. import { NextFunction, Request, Response, Router } from 'express';
  2. import { dtoValidationMiddleware } from '../middleware/validation';
  3. import { milvusService } from '../milvus';
  4. import { CollectionsService } from './collections.service';
  5. import {
  6. CreateAliasDto,
  7. CreateCollectionDto,
  8. InsertDataDto,
  9. ImportSampleDto,
  10. VectorSearchDto,
  11. QueryDto,
  12. RenameCollectionDto,
  13. DuplicateCollectionDto,
  14. } from './dto';
  15. import { LoadCollectionReq } from '@zilliz/milvus2-sdk-node';
  16. export class CollectionController {
  17. private collectionsService: CollectionsService;
  18. private router: Router;
  19. constructor() {
  20. this.collectionsService = new CollectionsService(milvusService);
  21. this.router = Router();
  22. }
  23. get collectionsServiceGetter() {
  24. return this.collectionsService;
  25. }
  26. generateRoutes() {
  27. this.router.get('/', this.showCollections.bind(this));
  28. this.router.post(
  29. '/',
  30. dtoValidationMiddleware(CreateCollectionDto),
  31. this.createCollection.bind(this)
  32. );
  33. this.router.get('/statistics', this.getStatistics.bind(this));
  34. this.router.get(
  35. '/:name/statistics',
  36. this.getCollectionStatistics.bind(this)
  37. );
  38. this.router.get(
  39. '/indexes/status',
  40. this.getCollectionsIndexStatus.bind(this)
  41. );
  42. this.router.delete('/:name', this.dropCollection.bind(this));
  43. this.router.post(
  44. '/:name',
  45. dtoValidationMiddleware(RenameCollectionDto),
  46. this.renameCollection.bind(this)
  47. );
  48. this.router.post(
  49. '/:name/duplicate',
  50. dtoValidationMiddleware(DuplicateCollectionDto),
  51. this.duplicateCollection.bind(this)
  52. );
  53. this.router.delete('/:name/alias/:alias', this.dropAlias.bind(this));
  54. // collection with index info
  55. this.router.get('/:name', this.describeCollection.bind(this));
  56. // just collection info
  57. this.router.get('/:name/info', this.getCollectionInfo.bind(this));
  58. this.router.get('/:name/count', this.count.bind(this));
  59. // load / release
  60. this.router.put('/:name/load', this.loadCollection.bind(this));
  61. this.router.put('/:name/release', this.releaseCollection.bind(this));
  62. this.router.post(
  63. '/:name/insert',
  64. dtoValidationMiddleware(InsertDataDto),
  65. this.insert.bind(this)
  66. );
  67. this.router.post(
  68. '/:name/importSample',
  69. dtoValidationMiddleware(ImportSampleDto),
  70. this.importSample.bind(this)
  71. );
  72. // we need use req.body, so we can't use delete here
  73. this.router.put('/:name/entities', this.deleteEntities.bind(this));
  74. this.router.post(
  75. '/:name/search',
  76. dtoValidationMiddleware(VectorSearchDto),
  77. this.vectorSearch.bind(this)
  78. );
  79. this.router.post(
  80. '/:name/query',
  81. dtoValidationMiddleware(QueryDto),
  82. this.query.bind(this)
  83. );
  84. this.router.post(
  85. '/:name/alias',
  86. dtoValidationMiddleware(CreateAliasDto),
  87. this.createAlias.bind(this)
  88. );
  89. // segments
  90. this.router.get('/:name/psegments', this.getPSegment.bind(this));
  91. this.router.get('/:name/qsegments', this.getQSegment.bind(this));
  92. this.router.put('/:name/compact', this.compact.bind(this));
  93. return this.router;
  94. }
  95. async showCollections(req: Request, res: Response, next: NextFunction) {
  96. const type = parseInt('' + req.query?.type, 10);
  97. try {
  98. const result =
  99. type === 1
  100. ? await this.collectionsService.getLoadedCollections()
  101. : await this.collectionsService.getAllCollections();
  102. res.send(result);
  103. } catch (error) {
  104. next(error);
  105. }
  106. }
  107. async getStatistics(req: Request, res: Response, next: NextFunction) {
  108. try {
  109. const result = await this.collectionsService.getStatistics();
  110. res.send(result);
  111. } catch (error) {
  112. next(error);
  113. }
  114. }
  115. async createCollection(req: Request, res: Response, next: NextFunction) {
  116. const createCollectionData = req.body;
  117. try {
  118. const result = await this.collectionsService.createCollection(
  119. createCollectionData
  120. );
  121. res.send(result);
  122. } catch (error) {
  123. next(error);
  124. }
  125. }
  126. async renameCollection(req: Request, res: Response, next: NextFunction) {
  127. const name = req.params?.name;
  128. const data = req.body;
  129. try {
  130. const result = await this.collectionsService.renameCollection({
  131. collection_name: name,
  132. ...data,
  133. });
  134. res.send(result);
  135. } catch (error) {
  136. next(error);
  137. }
  138. }
  139. async duplicateCollection(req: Request, res: Response, next: NextFunction) {
  140. const name = req.params?.name;
  141. const data = req.body;
  142. try {
  143. const result = await this.collectionsService.duplicateCollection({
  144. collection_name: name,
  145. ...data,
  146. });
  147. res.send(result);
  148. } catch (error) {
  149. next(error);
  150. }
  151. }
  152. async dropCollection(req: Request, res: Response, next: NextFunction) {
  153. const name = req.params?.name;
  154. try {
  155. const result = await this.collectionsService.dropCollection({
  156. collection_name: name,
  157. });
  158. res.send(result);
  159. } catch (error) {
  160. next(error);
  161. }
  162. }
  163. async describeCollection(req: Request, res: Response, next: NextFunction) {
  164. const name = req.params?.name;
  165. try {
  166. const result = await this.collectionsService.getAllCollections({
  167. data: [{ name }],
  168. });
  169. res.send(result[0]);
  170. } catch (error) {
  171. next(error);
  172. }
  173. }
  174. async getCollectionInfo(req: Request, res: Response, next: NextFunction) {
  175. const name = req.params?.name;
  176. try {
  177. const result = await this.collectionsService.describeCollection({
  178. collection_name: name,
  179. });
  180. res.send(result);
  181. } catch (error) {
  182. next(error);
  183. }
  184. }
  185. async getCollectionStatistics(
  186. req: Request,
  187. res: Response,
  188. next: NextFunction
  189. ) {
  190. const name = req.params?.name;
  191. try {
  192. const result = await this.collectionsService.getCollectionStatistics({
  193. collection_name: name,
  194. });
  195. res.send(result);
  196. } catch (error) {
  197. next(error);
  198. }
  199. }
  200. async getCollectionsIndexStatus(
  201. req: Request,
  202. res: Response,
  203. next: NextFunction
  204. ) {
  205. try {
  206. const result = await this.collectionsService.getCollectionsIndexStatus();
  207. res.send(result);
  208. } catch (error) {
  209. next(error);
  210. }
  211. }
  212. async loadCollection(req: Request, res: Response, next: NextFunction) {
  213. const collection_name = req.params?.name;
  214. const data = req.body;
  215. const param: LoadCollectionReq = { collection_name };
  216. if (data.replica_number) {
  217. param.replica_number = Number(data.replica_number);
  218. }
  219. try {
  220. const result = await this.collectionsService.loadCollection(param);
  221. res.send(result);
  222. } catch (error) {
  223. next(error);
  224. }
  225. }
  226. async releaseCollection(req: Request, res: Response, next: NextFunction) {
  227. const name = req.params?.name;
  228. try {
  229. const result = await this.collectionsService.releaseCollection({
  230. collection_name: name,
  231. });
  232. res.send(result);
  233. } catch (error) {
  234. next(error);
  235. }
  236. }
  237. async insert(req: Request, res: Response, next: NextFunction) {
  238. const name = req.params?.name;
  239. const data = req.body;
  240. try {
  241. const result = await this.collectionsService.insert({
  242. collection_name: name,
  243. ...data,
  244. });
  245. res.send(result);
  246. } catch (error) {
  247. next(error);
  248. }
  249. }
  250. async importSample(req: Request, res: Response, next: NextFunction) {
  251. const data = req.body;
  252. try {
  253. const result = await this.collectionsService.importSample({
  254. ...data,
  255. });
  256. res.send(result);
  257. } catch (error) {
  258. next(error);
  259. }
  260. }
  261. async deleteEntities(req: Request, res: Response, next: NextFunction) {
  262. const name = req.params?.name;
  263. const data = req.body;
  264. try {
  265. const result = await this.collectionsService.deleteEntities({
  266. collection_name: name,
  267. ...data,
  268. });
  269. res.send(result);
  270. } catch (error) {
  271. next(error);
  272. }
  273. }
  274. async vectorSearch(req: Request, res: Response, next: NextFunction) {
  275. const name = req.params?.name;
  276. const data = req.body;
  277. try {
  278. const result = await this.collectionsService.vectorSearch({
  279. collection_name: name,
  280. ...data,
  281. });
  282. res.send(result);
  283. } catch (error) {
  284. next(error);
  285. }
  286. }
  287. async query(req: Request, res: Response, next: NextFunction) {
  288. const name = req.params?.name;
  289. const data = req.body;
  290. const resultLimit: any = req.query?.limit;
  291. const resultPage: any = req.query?.page;
  292. try {
  293. const limit = isNaN(resultLimit) ? 100 : parseInt(resultLimit, 10);
  294. const page = isNaN(resultPage) ? 0 : parseInt(resultPage, 10);
  295. // TODO: add page and limit to node SDK
  296. // Here may raise "Error: 8 RESOURCE_EXHAUSTED: Received message larger than max"
  297. const result = await this.collectionsService.query({
  298. collection_name: name,
  299. ...data,
  300. });
  301. // const queryResultList = result.data;
  302. const queryResultLength = result.data.length;
  303. // const startNum = page * limit;
  304. // const endNum = (page + 1) * limit;
  305. // const slicedResult = queryResultList.slice(startNum, endNum);
  306. // result.data = slicedResult;
  307. res.send({ ...result, limit, page, total: queryResultLength });
  308. } catch (error) {
  309. next(error);
  310. }
  311. }
  312. async createAlias(req: Request, res: Response, next: NextFunction) {
  313. const name = req.params?.name;
  314. const data = req.body;
  315. try {
  316. const result = await this.collectionsService.createAlias({
  317. collection_name: name,
  318. ...data,
  319. });
  320. res.send(result);
  321. } catch (error) {
  322. next(error);
  323. }
  324. }
  325. async dropAlias(req: Request, res: Response, next: NextFunction) {
  326. const alias = req.params?.alias;
  327. try {
  328. const result = await this.collectionsService.dropAlias({ alias });
  329. res.send(result);
  330. } catch (error) {
  331. next(error);
  332. }
  333. }
  334. async getReplicas(req: Request, res: Response, next: NextFunction) {
  335. const collectionID = req.params?.collectionID;
  336. try {
  337. const result = await this.collectionsService.getReplicas({
  338. collectionID,
  339. });
  340. res.send(result);
  341. } catch (error) {
  342. next(error);
  343. }
  344. }
  345. async getPSegment(req: Request, res: Response, next: NextFunction) {
  346. const name = req.params?.name;
  347. try {
  348. const result = await this.collectionsService.getPersistentSegmentInfo({
  349. collectionName: name,
  350. });
  351. res.send(result);
  352. } catch (error) {
  353. next(error);
  354. }
  355. }
  356. async getQSegment(req: Request, res: Response, next: NextFunction) {
  357. const name = req.params?.name;
  358. try {
  359. const result = await this.collectionsService.getQuerySegmentInfo({
  360. collectionName: name,
  361. });
  362. res.send(result);
  363. } catch (error) {
  364. next(error);
  365. }
  366. }
  367. async compact(req: Request, res: Response, next: NextFunction) {
  368. const name = req.params?.name;
  369. try {
  370. const result = await this.collectionsService.compact({
  371. collection_name: name,
  372. });
  373. res.send(result);
  374. } catch (error) {
  375. next(error);
  376. }
  377. }
  378. async count(req: Request, res: Response, next: NextFunction) {
  379. const name = req.params?.name;
  380. try {
  381. const { value } = await this.collectionsService.hasCollection({
  382. collection_name: name,
  383. });
  384. let result: any = '';
  385. if (value) {
  386. result = await this.collectionsService.count({
  387. collection_name: name,
  388. });
  389. }
  390. res.send({ collection_name: name, rowCount: result });
  391. } catch (error) {
  392. next(error);
  393. }
  394. }
  395. }