Skip to content

Commit 79a4bda

Browse files
committed
Merge branch 'master' into vkarpov15/gh-13529
2 parents cb33093 + b336ed8 commit 79a4bda

File tree

6 files changed

+85
-15
lines changed

6 files changed

+85
-15
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
7.3.2 / 2023-07-06
2+
==================
3+
* fix(model): avoid TypeError if insertMany() fails with error that does not have writeErrors property #13579 #13531
4+
* fix(query): convert findOneAndUpdate to findOneAndReplace when overwrite set for backwards compat with Mongoose 6 #13572 #13550
5+
* fix(query): throw readable error when executing a Query instance without an associated model #13571 #13570
6+
* types: support mongoose.Schema.ObjectId as alias for mongoose.Schema.Types.ObjectId #13543 #13534
7+
* docs(connections): clarify that socketTimeoutMS now defaults to 0 #13576 #13537
8+
* docs(migrating_to_7): add mapReduce() removal to migration guide #13568 #13548
9+
* docs(schemas): fix typo in schemas.md #13540 [Metehan-Altuntekin](https://github.com/Metehan-Altuntekin)
10+
111
7.3.1 / 2023-06-21
212
==================
313
* fix(query): respect query-level strict option on findOneAndReplace() #13516 #13507

lib/model.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3234,16 +3234,19 @@ Model.$__insertMany = function(arr, options, callback) {
32343234
}
32353235

32363236
// `insertedDocs` is a Mongoose-specific property
3237+
const hasWriteErrors = error && error.writeErrors;
32373238
const erroredIndexes = new Set((error && error.writeErrors || []).map(err => err.index));
32383239

3239-
for (let i = 0; i < error.writeErrors.length; ++i) {
3240-
const originalIndex = validDocIndexToOriginalIndex.get(error.writeErrors[i].index);
3241-
error.writeErrors[i] = {
3242-
...error.writeErrors[i],
3243-
index: originalIndex
3244-
};
3245-
if (!ordered) {
3246-
results[originalIndex] = error.writeErrors[i];
3240+
if (error.writeErrors != null) {
3241+
for (let i = 0; i < error.writeErrors.length; ++i) {
3242+
const originalIndex = validDocIndexToOriginalIndex.get(error.writeErrors[i].index);
3243+
error.writeErrors[i] = {
3244+
...error.writeErrors[i],
3245+
index: originalIndex
3246+
};
3247+
if (!ordered) {
3248+
results[originalIndex] = error.writeErrors[i];
3249+
}
32473250
}
32483251
}
32493252

@@ -3260,7 +3263,7 @@ Model.$__insertMany = function(arr, options, callback) {
32603263
let firstErroredIndex = -1;
32613264
error.insertedDocs = docAttributes.
32623265
filter((doc, i) => {
3263-
const isErrored = erroredIndexes.has(i);
3266+
const isErrored = !hasWriteErrors || erroredIndexes.has(i);
32643267

32653268
if (ordered) {
32663269
if (firstErroredIndex > -1) {

lib/query.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3281,6 +3281,12 @@ Query.prototype.findOneAndUpdate = function(filter, doc, options) {
32813281
*/
32823282

32833283
Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
3284+
// For backwards compability with Mongoose 6 re: #13550
3285+
if (this._mongooseOptions.overwrite) {
3286+
this.op = 'findOneAndReplace';
3287+
return this._findOneAndReplace();
3288+
}
3289+
32843290
this._castConditions();
32853291

32863292
_castArrayFilters(this);
@@ -4354,7 +4360,10 @@ Query.prototype.exec = async function exec(op) {
43544360
}
43554361

43564362
if (this.op == null) {
4357-
throw new Error('Query must have `op` before executing');
4363+
throw new MongooseError('Query must have `op` before executing');
4364+
}
4365+
if (this.model == null) {
4366+
throw new MongooseError('Query must have an associated model before executing');
43584367
}
43594368
this._validateOp();
43604369

@@ -4434,6 +4443,13 @@ function _executePostExecHooks(query) {
44344443
*/
44354444

44364445
function _executePostHooks(query, res, error, op) {
4446+
if (query._queryMiddleware == null) {
4447+
if (error != null) {
4448+
throw error;
4449+
}
4450+
return res;
4451+
}
4452+
44374453
return new Promise((resolve, reject) => {
44384454
const opts = error ? { error } : {};
44394455

@@ -4467,6 +4483,10 @@ function _executePreExecHooks(query) {
44674483
*/
44684484

44694485
function _executePreHooks(query, op) {
4486+
if (query._queryMiddleware == null) {
4487+
return;
4488+
}
4489+
44704490
return new Promise((resolve, reject) => {
44714491
query._queryMiddleware.execPre(op || query.op, query, [], (error) => {
44724492
if (error != null) {

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "mongoose",
33
"description": "Mongoose MongoDB ODM",
4-
"version": "7.3.1",
4+
"version": "7.3.2",
55
"author": "Guillermo Rauch <[email protected]>",
66
"keywords": [
77
"mongodb",
@@ -30,8 +30,8 @@
3030
"devDependencies": {
3131
"@babel/core": "7.22.5",
3232
"@babel/preset-env": "7.22.5",
33-
"@typescript-eslint/eslint-plugin": "5.60.1",
34-
"@typescript-eslint/parser": "5.60.1",
33+
"@typescript-eslint/eslint-plugin": "5.61.0",
34+
"@typescript-eslint/parser": "5.61.0",
3535
"acquit": "1.3.0",
3636
"acquit-ignore": "0.2.1",
3737
"acquit-require": "0.1.1",
@@ -56,7 +56,7 @@
5656
"lodash.isequalwith": "4.4.0",
5757
"markdownlint-cli2": "^0.8.1",
5858
"marked": "4.3.0",
59-
"mkdirp": "^2.1.3",
59+
"mkdirp": "^3.0.1",
6060
"mocha": "10.2.0",
6161
"moment": "2.x",
6262
"mongodb-memory-server": "8.13.0",

test/query.test.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4094,6 +4094,7 @@ describe('Query', function() {
40944094
await Test.findOneAndUpdate({}, { name: 'bar' });
40954095
assert.ok(!('projection' in lastOptions));
40964096
});
4097+
40974098
it('should provide a clearer error message when sorting with empty string', async function() {
40984099
const testSchema = new Schema({
40994100
name: { type: String }
@@ -4104,4 +4105,40 @@ describe('Query', function() {
41044105
await Error.find().sort('-');
41054106
}, { message: 'Invalid field "" passed to sort()' });
41064107
});
4108+
4109+
it('throws a readable error when executing Query instance without a model (gh-13570)', async function() {
4110+
const schema = new Schema({ name: String });
4111+
const M = db.model('Test', schema, 'Test');
4112+
await M.deleteMany({});
4113+
await M.create({ name: 'gh13570' });
4114+
4115+
const Q = new mongoose.Query();
4116+
await assert.rejects(
4117+
() => Q.collection('Test').find().lean(),
4118+
/Query must have an associated model before executing/
4119+
);
4120+
});
4121+
4122+
it('throws a readable error when executing Query instance without an op (gh-13570)', async function() {
4123+
const schema = new Schema({ name: String });
4124+
const M = db.model('Test', schema, 'Test');
4125+
await M.deleteMany({});
4126+
await M.create({ name: 'gh13570' });
4127+
4128+
const Q = new M.Query();
4129+
await assert.rejects(
4130+
() => Q.lean(),
4131+
/Query must have `op` before executing/
4132+
);
4133+
});
4134+
it('converts findOneAndUpdate to findOneAndReplace if overwrite set (gh-13550)', async function() {
4135+
const testSchema = new Schema({
4136+
name: { type: String }
4137+
});
4138+
4139+
const Test = db.model('Test', testSchema);
4140+
const q = Test.findOneAndUpdate({}, { name: 'bar' }, { overwrite: true });
4141+
await q.exec();
4142+
assert.equal(q.op, 'findOneAndReplace');
4143+
});
41074144
});

types/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ declare module 'mongoose' {
197197

198198
export type DiscriminatorSchema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods, DisSchema> =
199199
DisSchema extends Schema<infer DisSchemaEDocType, infer DisSchemaM, infer DisSchemaInstanceMethods, infer DisSchemaQueryhelpers, infer DisSchemaVirtuals, infer DisSchemaStatics>
200-
? Schema<Omit<DocType, keyof DisSchemaEDocType> & DisSchemaEDocType, DiscriminatorModel<DisSchemaM, M>, DisSchemaInstanceMethods | TInstanceMethods, DisSchemaQueryhelpers | TQueryHelpers, DisSchemaVirtuals | TVirtuals, DisSchemaStatics & TStaticMethods>
200+
? Schema<MergeType<DocType, DisSchemaEDocType>, DiscriminatorModel<DisSchemaM, M>, DisSchemaInstanceMethods | TInstanceMethods, DisSchemaQueryhelpers | TQueryHelpers, DisSchemaVirtuals | TVirtuals, DisSchemaStatics & TStaticMethods>
201201
: Schema<DocType, M, TInstanceMethods, TQueryHelpers, TVirtuals, TStaticMethods>;
202202

203203
type QueryResultType<T> = T extends Query<infer ResultType, any> ? ResultType : never;

0 commit comments

Comments
 (0)