update.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.ReplaceOneOperation = exports.UpdateManyOperation = exports.UpdateOneOperation = exports.UpdateOperation = void 0;
  4. exports.makeUpdateStatement = makeUpdateStatement;
  5. const responses_1 = require("../cmap/wire_protocol/responses");
  6. const error_1 = require("../error");
  7. const sort_1 = require("../sort");
  8. const utils_1 = require("../utils");
  9. const command_1 = require("./command");
  10. const operation_1 = require("./operation");
  11. /**
  12. * @internal
  13. * UpdateOperation is used in bulk write, while UpdateOneOperation and UpdateManyOperation are only used in the collections API
  14. */
  15. class UpdateOperation extends command_1.CommandOperation {
  16. constructor(ns, statements, options) {
  17. super(undefined, options);
  18. this.SERVER_COMMAND_RESPONSE_TYPE = responses_1.MongoDBResponse;
  19. this.options = options;
  20. this.ns = ns;
  21. this.statements = statements;
  22. }
  23. get commandName() {
  24. return 'update';
  25. }
  26. get canRetryWrite() {
  27. if (super.canRetryWrite === false) {
  28. return false;
  29. }
  30. return this.statements.every(op => op.multi == null || op.multi === false);
  31. }
  32. buildCommandDocument(_connection, _session) {
  33. const options = this.options;
  34. const command = {
  35. update: this.ns.collection,
  36. updates: this.statements,
  37. ordered: options.ordered ?? true
  38. };
  39. if (typeof options.bypassDocumentValidation === 'boolean') {
  40. command.bypassDocumentValidation = options.bypassDocumentValidation;
  41. }
  42. if (options.let) {
  43. command.let = options.let;
  44. }
  45. // we check for undefined specifically here to allow falsy values
  46. // eslint-disable-next-line no-restricted-syntax
  47. if (options.comment !== undefined) {
  48. command.comment = options.comment;
  49. }
  50. return command;
  51. }
  52. }
  53. exports.UpdateOperation = UpdateOperation;
  54. /** @internal */
  55. class UpdateOneOperation extends UpdateOperation {
  56. constructor(ns, filter, update, options) {
  57. super(ns, [makeUpdateStatement(filter, update, { ...options, multi: false })], options);
  58. if (!(0, utils_1.hasAtomicOperators)(update, options)) {
  59. throw new error_1.MongoInvalidArgumentError('Update document requires atomic operators');
  60. }
  61. }
  62. handleOk(response) {
  63. const res = super.handleOk(response);
  64. // @ts-expect-error Explain typing is broken
  65. if (this.explain != null)
  66. return res;
  67. if (res.code)
  68. throw new error_1.MongoServerError(res);
  69. if (res.writeErrors)
  70. throw new error_1.MongoServerError(res.writeErrors[0]);
  71. return {
  72. acknowledged: this.writeConcern?.w !== 0,
  73. modifiedCount: res.nModified ?? res.n,
  74. upsertedId: Array.isArray(res.upserted) && res.upserted.length > 0 ? res.upserted[0]._id : null,
  75. upsertedCount: Array.isArray(res.upserted) && res.upserted.length ? res.upserted.length : 0,
  76. matchedCount: Array.isArray(res.upserted) && res.upserted.length > 0 ? 0 : res.n
  77. };
  78. }
  79. }
  80. exports.UpdateOneOperation = UpdateOneOperation;
  81. /** @internal */
  82. class UpdateManyOperation extends UpdateOperation {
  83. constructor(ns, filter, update, options) {
  84. super(ns, [makeUpdateStatement(filter, update, { ...options, multi: true })], options);
  85. if (!(0, utils_1.hasAtomicOperators)(update, options)) {
  86. throw new error_1.MongoInvalidArgumentError('Update document requires atomic operators');
  87. }
  88. }
  89. handleOk(response) {
  90. const res = super.handleOk(response);
  91. // @ts-expect-error Explain typing is broken
  92. if (this.explain != null)
  93. return res;
  94. if (res.code)
  95. throw new error_1.MongoServerError(res);
  96. if (res.writeErrors)
  97. throw new error_1.MongoServerError(res.writeErrors[0]);
  98. return {
  99. acknowledged: this.writeConcern?.w !== 0,
  100. modifiedCount: res.nModified ?? res.n,
  101. upsertedId: Array.isArray(res.upserted) && res.upserted.length > 0 ? res.upserted[0]._id : null,
  102. upsertedCount: Array.isArray(res.upserted) && res.upserted.length ? res.upserted.length : 0,
  103. matchedCount: Array.isArray(res.upserted) && res.upserted.length > 0 ? 0 : res.n
  104. };
  105. }
  106. }
  107. exports.UpdateManyOperation = UpdateManyOperation;
  108. /** @internal */
  109. class ReplaceOneOperation extends UpdateOperation {
  110. constructor(ns, filter, replacement, options) {
  111. super(ns, [makeUpdateStatement(filter, replacement, { ...options, multi: false })], options);
  112. if ((0, utils_1.hasAtomicOperators)(replacement)) {
  113. throw new error_1.MongoInvalidArgumentError('Replacement document must not contain atomic operators');
  114. }
  115. }
  116. handleOk(response) {
  117. const res = super.handleOk(response);
  118. // @ts-expect-error Explain typing is broken
  119. if (this.explain != null)
  120. return res;
  121. if (res.code)
  122. throw new error_1.MongoServerError(res);
  123. if (res.writeErrors)
  124. throw new error_1.MongoServerError(res.writeErrors[0]);
  125. return {
  126. acknowledged: this.writeConcern?.w !== 0,
  127. modifiedCount: res.nModified ?? res.n,
  128. upsertedId: Array.isArray(res.upserted) && res.upserted.length > 0 ? res.upserted[0]._id : null,
  129. upsertedCount: Array.isArray(res.upserted) && res.upserted.length ? res.upserted.length : 0,
  130. matchedCount: Array.isArray(res.upserted) && res.upserted.length > 0 ? 0 : res.n
  131. };
  132. }
  133. }
  134. exports.ReplaceOneOperation = ReplaceOneOperation;
  135. function makeUpdateStatement(filter, update, options) {
  136. if (filter == null || typeof filter !== 'object') {
  137. throw new error_1.MongoInvalidArgumentError('Selector must be a valid JavaScript object');
  138. }
  139. if (update == null || typeof update !== 'object') {
  140. throw new error_1.MongoInvalidArgumentError('Document must be a valid JavaScript object');
  141. }
  142. const op = { q: filter, u: update };
  143. if (typeof options.upsert === 'boolean') {
  144. op.upsert = options.upsert;
  145. }
  146. if (options.multi) {
  147. op.multi = options.multi;
  148. }
  149. if (options.hint) {
  150. op.hint = options.hint;
  151. }
  152. if (options.arrayFilters) {
  153. op.arrayFilters = options.arrayFilters;
  154. }
  155. if (options.collation) {
  156. op.collation = options.collation;
  157. }
  158. if (!options.multi && options.sort != null) {
  159. op.sort = (0, sort_1.formatSort)(options.sort);
  160. }
  161. return op;
  162. }
  163. (0, operation_1.defineAspects)(UpdateOperation, [
  164. operation_1.Aspect.RETRYABLE,
  165. operation_1.Aspect.WRITE_OPERATION,
  166. operation_1.Aspect.SKIP_COLLATION,
  167. operation_1.Aspect.SUPPORTS_RAW_DATA
  168. ]);
  169. (0, operation_1.defineAspects)(UpdateOneOperation, [
  170. operation_1.Aspect.RETRYABLE,
  171. operation_1.Aspect.WRITE_OPERATION,
  172. operation_1.Aspect.EXPLAINABLE,
  173. operation_1.Aspect.SKIP_COLLATION,
  174. operation_1.Aspect.SUPPORTS_RAW_DATA
  175. ]);
  176. (0, operation_1.defineAspects)(UpdateManyOperation, [
  177. operation_1.Aspect.WRITE_OPERATION,
  178. operation_1.Aspect.EXPLAINABLE,
  179. operation_1.Aspect.SKIP_COLLATION,
  180. operation_1.Aspect.SUPPORTS_RAW_DATA
  181. ]);
  182. (0, operation_1.defineAspects)(ReplaceOneOperation, [
  183. operation_1.Aspect.RETRYABLE,
  184. operation_1.Aspect.WRITE_OPERATION,
  185. operation_1.Aspect.SKIP_COLLATION,
  186. operation_1.Aspect.SUPPORTS_RAW_DATA
  187. ]);
  188. //# sourceMappingURL=update.js.map