Spaces:
Runtime error
Runtime error
File size: 5,640 Bytes
9756872 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | import type { Document } from '../bson';
import type { BulkWriteOptions } from '../bulk/common';
import type { Collection } from '../collection';
import { MongoInvalidArgumentError, MongoServerError } from '../error';
import type { InferIdType } from '../mongo_types';
import type { Server } from '../sdam/server';
import type { ClientSession } from '../sessions';
import type { MongoDBNamespace } from '../utils';
import { maybeAddIdToDocuments } from '../utils';
import { WriteConcern } from '../write_concern';
import { BulkWriteOperation } from './bulk_write';
import { CommandOperation, type CommandOperationOptions } from './command';
import { AbstractOperation, Aspect, defineAspects } from './operation';
/** @internal */
export class InsertOperation extends CommandOperation<Document> {
override options: BulkWriteOptions;
documents: Document[];
constructor(ns: MongoDBNamespace, documents: Document[], options: BulkWriteOptions) {
super(undefined, options);
this.options = { ...options, checkKeys: options.checkKeys ?? false };
this.ns = ns;
this.documents = documents;
}
override get commandName() {
return 'insert' as const;
}
override async execute(server: Server, session: ClientSession | undefined): Promise<Document> {
const options = this.options ?? {};
const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
const command: Document = {
insert: this.ns.collection,
documents: this.documents,
ordered
};
if (typeof options.bypassDocumentValidation === 'boolean') {
command.bypassDocumentValidation = options.bypassDocumentValidation;
}
// we check for undefined specifically here to allow falsy values
// eslint-disable-next-line no-restricted-syntax
if (options.comment !== undefined) {
command.comment = options.comment;
}
return await super.executeCommand(server, session, command);
}
}
/** @public */
export interface InsertOneOptions extends CommandOperationOptions {
/** Allow driver to bypass schema validation. */
bypassDocumentValidation?: boolean;
/** Force server to assign _id values instead of driver. */
forceServerObjectId?: boolean;
}
/** @public */
export interface InsertOneResult<TSchema = Document> {
/** Indicates whether this write result was acknowledged. If not, then all other members of this result will be undefined */
acknowledged: boolean;
/** The identifier that was inserted. If the server generated the identifier, this value will be null as the driver does not have access to that data */
insertedId: InferIdType<TSchema>;
}
export class InsertOneOperation extends InsertOperation {
constructor(collection: Collection, doc: Document, options: InsertOneOptions) {
super(collection.s.namespace, maybeAddIdToDocuments(collection, [doc], options), options);
}
override async execute(
server: Server,
session: ClientSession | undefined
): Promise<InsertOneResult> {
const res = await super.execute(server, session);
if (res.code) throw new MongoServerError(res);
if (res.writeErrors) {
// This should be a WriteError but we can't change it now because of error hierarchy
throw new MongoServerError(res.writeErrors[0]);
}
return {
acknowledged: this.writeConcern?.w !== 0,
insertedId: this.documents[0]._id
};
}
}
/** @public */
export interface InsertManyResult<TSchema = Document> {
/** Indicates whether this write result was acknowledged. If not, then all other members of this result will be undefined */
acknowledged: boolean;
/** The number of inserted documents for this operations */
insertedCount: number;
/** Map of the index of the inserted document to the id of the inserted document */
insertedIds: { [key: number]: InferIdType<TSchema> };
}
/** @internal */
export class InsertManyOperation extends AbstractOperation<InsertManyResult> {
override options: BulkWriteOptions;
collection: Collection;
docs: Document[];
constructor(collection: Collection, docs: Document[], options: BulkWriteOptions) {
super(options);
if (!Array.isArray(docs)) {
throw new MongoInvalidArgumentError('Argument "docs" must be an array of documents');
}
this.options = options;
this.collection = collection;
this.docs = docs;
}
override get commandName() {
return 'insert' as const;
}
override async execute(
server: Server,
session: ClientSession | undefined
): Promise<InsertManyResult> {
const coll = this.collection;
const options = { ...this.options, ...this.bsonOptions, readPreference: this.readPreference };
const writeConcern = WriteConcern.fromOptions(options);
const bulkWriteOperation = new BulkWriteOperation(
coll,
this.docs.map(document => ({
insertOne: { document }
})),
options
);
try {
const res = await bulkWriteOperation.execute(server, session);
return {
acknowledged: writeConcern?.w !== 0,
insertedCount: res.insertedCount,
insertedIds: res.insertedIds
};
} catch (err) {
if (err && err.message === 'Operation must be an object with an operation key') {
throw new MongoInvalidArgumentError(
'Collection.insertMany() cannot be called with an array that has null/undefined values'
);
}
throw err;
}
}
}
defineAspects(InsertOperation, [Aspect.RETRYABLE, Aspect.WRITE_OPERATION]);
defineAspects(InsertOneOperation, [Aspect.RETRYABLE, Aspect.WRITE_OPERATION]);
defineAspects(InsertManyOperation, [Aspect.WRITE_OPERATION]);
|