estimated_document_count.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. 'use strict';
  2. const MONGODB_ERROR_CODES = require('../error_codes').MONGODB_ERROR_CODES;
  3. const Aspect = require('./operation').Aspect;
  4. const defineAspects = require('./operation').defineAspects;
  5. const CommandOperationV2 = require('./command_v2');
  6. const maxWireVersion = require('../core/utils').maxWireVersion;
  7. const CountDocumentsOperation = require('./count_documents');
  8. class EstimatedDocumentCountOperation extends CommandOperationV2 {
  9. constructor(collection, options) {
  10. super(collection, options);
  11. this.collection = collection;
  12. this.collectionName = collection.s.namespace.collection;
  13. }
  14. execute(server, callback) {
  15. if (maxWireVersion(server) < 12) {
  16. return this.executeLegacy(server, callback);
  17. }
  18. // if the user specifies a filter, use a CountDocumentsOperation instead
  19. if (this.options.query) {
  20. const op = new CountDocumentsOperation(this.collection, this.options.query, this.options);
  21. return op.execute(server, callback);
  22. }
  23. const pipeline = [{ $collStats: { count: {} } }, { $group: { _id: 1, n: { $sum: '$count' } } }];
  24. const cmd = { aggregate: this.collectionName, pipeline, cursor: {} };
  25. if (typeof this.options.maxTimeMS === 'number') {
  26. cmd.maxTimeMS = this.options.maxTimeMS;
  27. }
  28. super.executeCommand(server, cmd, (err, response) => {
  29. if (err && err.code !== MONGODB_ERROR_CODES.NamespaceNotFound) {
  30. callback(err);
  31. return;
  32. }
  33. callback(
  34. undefined,
  35. (response &&
  36. response.cursor &&
  37. response.cursor.firstBatch &&
  38. response.cursor.firstBatch[0].n) ||
  39. 0
  40. );
  41. });
  42. }
  43. executeLegacy(server, callback) {
  44. const cmd = { count: this.collectionName };
  45. const options = this.options;
  46. if (options.query) {
  47. cmd.query = options.query;
  48. }
  49. if (options.hint) {
  50. cmd.hint = options.hint;
  51. }
  52. if (typeof options.maxTimeMS === 'number') {
  53. cmd.maxTimeMS = options.maxTimeMS;
  54. }
  55. if (typeof options.skip === 'number') {
  56. cmd.skip = options.skip;
  57. }
  58. if (typeof options.limit === 'number') {
  59. cmd.limit = options.limit;
  60. }
  61. super.executeCommand(server, cmd, (err, response) => {
  62. if (err) {
  63. callback(err);
  64. return;
  65. }
  66. callback(null, response.n);
  67. });
  68. }
  69. }
  70. defineAspects(EstimatedDocumentCountOperation, [
  71. Aspect.READ_OPERATION,
  72. Aspect.RETRYABLE,
  73. Aspect.EXECUTE_WITH_SELECTION
  74. ]);
  75. module.exports = EstimatedDocumentCountOperation;