distinct.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. 'use strict';
  2. const Aspect = require('./operation').Aspect;
  3. const defineAspects = require('./operation').defineAspects;
  4. const CommandOperationV2 = require('./command_v2');
  5. const decorateWithCollation = require('../utils').decorateWithCollation;
  6. const decorateWithReadConcern = require('../utils').decorateWithReadConcern;
  7. const maxWireVersion = require('../core/utils').maxWireVersion;
  8. const MongoError = require('../error').MongoError;
  9. /**
  10. * Return a list of distinct values for the given key across a collection.
  11. *
  12. * @class
  13. * @property {Collection} a Collection instance.
  14. * @property {string} key Field of the document to find distinct values for.
  15. * @property {object} query The query for filtering the set of documents to which we apply the distinct filter.
  16. * @property {object} [options] Optional settings. See Collection.prototype.distinct for a list of options.
  17. */
  18. class DistinctOperation extends CommandOperationV2 {
  19. /**
  20. * Construct a Distinct operation.
  21. *
  22. * @param {Collection} a Collection instance.
  23. * @param {string} key Field of the document to find distinct values for.
  24. * @param {object} query The query for filtering the set of documents to which we apply the distinct filter.
  25. * @param {object} [options] Optional settings. See Collection.prototype.distinct for a list of options.
  26. */
  27. constructor(collection, key, query, options) {
  28. super(collection, options);
  29. this.collection = collection;
  30. this.key = key;
  31. this.query = query;
  32. }
  33. /**
  34. * Execute the operation.
  35. *
  36. * @param {Collection~resultCallback} [callback] The command result callback
  37. */
  38. execute(server, callback) {
  39. const coll = this.collection;
  40. const key = this.key;
  41. const query = this.query;
  42. const options = this.options;
  43. // Distinct command
  44. const cmd = {
  45. distinct: coll.collectionName,
  46. key: key,
  47. query: query
  48. };
  49. // Add maxTimeMS if defined
  50. if (typeof options.maxTimeMS === 'number') {
  51. cmd.maxTimeMS = options.maxTimeMS;
  52. }
  53. // Do we have a readConcern specified
  54. decorateWithReadConcern(cmd, coll, options);
  55. // Have we specified collation
  56. try {
  57. decorateWithCollation(cmd, coll, options);
  58. } catch (err) {
  59. return callback(err, null);
  60. }
  61. if (this.explain && maxWireVersion(server) < 4) {
  62. callback(new MongoError(`server does not support explain on distinct`));
  63. return;
  64. }
  65. super.executeCommand(server, cmd, (err, result) => {
  66. if (err) {
  67. callback(err);
  68. return;
  69. }
  70. callback(null, this.options.full || this.explain ? result : result.values);
  71. });
  72. }
  73. }
  74. defineAspects(DistinctOperation, [
  75. Aspect.READ_OPERATION,
  76. Aspect.RETRYABLE,
  77. Aspect.EXECUTE_WITH_SELECTION,
  78. Aspect.EXPLAINABLE
  79. ]);
  80. module.exports = DistinctOperation;