collections.controller.ts 11 KB

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