command.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. 'use strict';
  2. const Aspect = require('./operation').Aspect;
  3. const OperationBase = require('./operation').OperationBase;
  4. const applyWriteConcern = require('../utils').applyWriteConcern;
  5. const debugOptions = require('../utils').debugOptions;
  6. const handleCallback = require('../utils').handleCallback;
  7. const MongoError = require('../core').MongoError;
  8. const ReadPreference = require('../core').ReadPreference;
  9. const MongoDBNamespace = require('../utils').MongoDBNamespace;
  10. const debugFields = [
  11. 'authSource',
  12. 'w',
  13. 'wtimeout',
  14. 'j',
  15. 'native_parser',
  16. 'forceServerObjectId',
  17. 'serializeFunctions',
  18. 'raw',
  19. 'promoteLongs',
  20. 'promoteValues',
  21. 'promoteBuffers',
  22. 'bufferMaxEntries',
  23. 'numberOfRetries',
  24. 'retryMiliSeconds',
  25. 'readPreference',
  26. 'pkFactory',
  27. 'parentDb',
  28. 'promiseLibrary',
  29. 'noListener'
  30. ];
  31. class CommandOperation extends OperationBase {
  32. constructor(db, options, collection, command) {
  33. super(options);
  34. if (!this.hasAspect(Aspect.WRITE_OPERATION)) {
  35. if (collection != null) {
  36. this.options.readPreference = ReadPreference.resolve(collection, options);
  37. } else {
  38. this.options.readPreference = ReadPreference.resolve(db, options);
  39. }
  40. } else {
  41. if (collection != null) {
  42. applyWriteConcern(this.options, { db, coll: collection }, this.options);
  43. } else {
  44. applyWriteConcern(this.options, { db }, this.options);
  45. }
  46. this.options.readPreference = ReadPreference.primary;
  47. }
  48. this.db = db;
  49. if (command != null) {
  50. this.command = command;
  51. }
  52. if (collection != null) {
  53. this.collection = collection;
  54. }
  55. }
  56. _buildCommand() {
  57. if (this.command != null) {
  58. return this.command;
  59. }
  60. }
  61. execute(callback) {
  62. const db = this.db;
  63. const options = Object.assign({}, this.options);
  64. // Did the user destroy the topology
  65. if (db.serverConfig && db.serverConfig.isDestroyed()) {
  66. return callback(new MongoError('topology was destroyed'));
  67. }
  68. let command;
  69. try {
  70. command = this._buildCommand();
  71. } catch (e) {
  72. return callback(e);
  73. }
  74. // Get the db name we are executing against
  75. const dbName = options.dbName || options.authdb || db.databaseName;
  76. // Convert the readPreference if its not a write
  77. if (this.hasAspect(Aspect.WRITE_OPERATION)) {
  78. if (options.writeConcern && (!options.session || !options.session.inTransaction())) {
  79. command.writeConcern = options.writeConcern;
  80. }
  81. }
  82. // Debug information
  83. if (db.s.logger.isDebug()) {
  84. db.s.logger.debug(
  85. `executing command ${JSON.stringify(
  86. command
  87. )} against ${dbName}.$cmd with options [${JSON.stringify(
  88. debugOptions(debugFields, options)
  89. )}]`
  90. );
  91. }
  92. const namespace =
  93. this.namespace != null ? this.namespace : new MongoDBNamespace(dbName, '$cmd');
  94. // Execute command
  95. db.s.topology.command(namespace, command, options, (err, result) => {
  96. if (err) return handleCallback(callback, err);
  97. if (options.full) return handleCallback(callback, null, result);
  98. handleCallback(callback, null, result.result);
  99. });
  100. }
  101. }
  102. module.exports = CommandOperation;