list_collections.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. 'use strict';
  2. const CommandOperationV2 = require('./command_v2');
  3. const Aspect = require('./operation').Aspect;
  4. const defineAspects = require('./operation').defineAspects;
  5. const maxWireVersion = require('../core/utils').maxWireVersion;
  6. const CONSTANTS = require('../constants');
  7. const LIST_COLLECTIONS_WIRE_VERSION = 3;
  8. function listCollectionsTransforms(databaseName) {
  9. const matching = `${databaseName}.`;
  10. return {
  11. doc: doc => {
  12. const index = doc.name.indexOf(matching);
  13. // Remove database name if available
  14. if (doc.name && index === 0) {
  15. doc.name = doc.name.substr(index + matching.length);
  16. }
  17. return doc;
  18. }
  19. };
  20. }
  21. class ListCollectionsOperation extends CommandOperationV2 {
  22. constructor(db, filter, options) {
  23. super(db, options, { fullResponse: true });
  24. this.db = db;
  25. this.filter = filter;
  26. this.nameOnly = !!this.options.nameOnly;
  27. if (typeof this.options.batchSize === 'number') {
  28. this.batchSize = this.options.batchSize;
  29. }
  30. }
  31. execute(server, callback) {
  32. if (maxWireVersion(server) < LIST_COLLECTIONS_WIRE_VERSION) {
  33. let filter = this.filter;
  34. const databaseName = this.db.s.namespace.db;
  35. // If we have legacy mode and have not provided a full db name filter it
  36. if (
  37. typeof filter.name === 'string' &&
  38. !new RegExp('^' + databaseName + '\\.').test(filter.name)
  39. ) {
  40. filter = Object.assign({}, filter);
  41. filter.name = this.db.s.namespace.withCollection(filter.name).toString();
  42. }
  43. // No filter, filter by current database
  44. if (filter == null) {
  45. filter.name = `/${databaseName}/`;
  46. }
  47. // Rewrite the filter to use $and to filter out indexes
  48. if (filter.name) {
  49. filter = { $and: [{ name: filter.name }, { name: /^((?!\$).)*$/ }] };
  50. } else {
  51. filter = { name: /^((?!\$).)*$/ };
  52. }
  53. const transforms = listCollectionsTransforms(databaseName);
  54. server.query(
  55. `${databaseName}.${CONSTANTS.SYSTEM_NAMESPACE_COLLECTION}`,
  56. { query: filter },
  57. { batchSize: this.batchSize || 1000 },
  58. {},
  59. (err, result) => {
  60. if (
  61. result &&
  62. result.message &&
  63. result.message.documents &&
  64. Array.isArray(result.message.documents)
  65. ) {
  66. result.message.documents = result.message.documents.map(transforms.doc);
  67. }
  68. callback(err, result);
  69. }
  70. );
  71. return;
  72. }
  73. const command = {
  74. listCollections: 1,
  75. filter: this.filter,
  76. cursor: this.batchSize ? { batchSize: this.batchSize } : {},
  77. nameOnly: this.nameOnly
  78. };
  79. return super.executeCommand(server, command, callback);
  80. }
  81. }
  82. defineAspects(ListCollectionsOperation, [
  83. Aspect.READ_OPERATION,
  84. Aspect.RETRYABLE,
  85. Aspect.EXECUTE_WITH_SELECTION
  86. ]);
  87. module.exports = ListCollectionsOperation;