-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14915 from Automattic/8.7
8.7
- Loading branch information
Showing
21 changed files
with
629 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/*! | ||
* Module dependencies. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const MongooseError = require('./mongooseError'); | ||
|
||
|
||
/** | ||
* If the underwriting `bulkWrite()` for `bulkSave()` succeeded, but wasn't able to update or | ||
* insert all documents, we throw this error. | ||
* | ||
* @api private | ||
*/ | ||
|
||
class MongooseBulkSaveIncompleteError extends MongooseError { | ||
constructor(modelName, documents, bulkWriteResult) { | ||
const matchedCount = bulkWriteResult?.matchedCount ?? 0; | ||
const insertedCount = bulkWriteResult?.insertedCount ?? 0; | ||
let preview = documents.map(doc => doc._id).join(', '); | ||
if (preview.length > 100) { | ||
preview = preview.slice(0, 100) + '...'; | ||
} | ||
|
||
const numDocumentsNotUpdated = documents.length - matchedCount - insertedCount; | ||
super(`${modelName}.bulkSave() was not able to update ${numDocumentsNotUpdated} of the given documents due to incorrect version or optimistic concurrency, document ids: ${preview}`); | ||
|
||
this.modelName = modelName; | ||
this.documents = documents; | ||
this.bulkWriteResult = bulkWriteResult; | ||
this.numDocumentsNotUpdated = numDocumentsNotUpdated; | ||
} | ||
} | ||
|
||
Object.defineProperty(MongooseBulkSaveIncompleteError.prototype, 'name', { | ||
value: 'MongooseBulkSaveIncompleteError' | ||
}); | ||
|
||
/*! | ||
* exports | ||
*/ | ||
|
||
module.exports = MongooseBulkSaveIncompleteError; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
'use strict'; | ||
|
||
const mpath = require('mpath'); | ||
|
||
module.exports = applyVirtuals; | ||
|
||
/** | ||
* Apply a given schema's virtuals to a given POJO | ||
* | ||
* @param {Schema} schema | ||
* @param {Object} obj | ||
* @param {Array<string>} [virtuals] optional whitelist of virtuals to apply | ||
* @returns | ||
*/ | ||
|
||
function applyVirtuals(schema, obj, virtuals) { | ||
if (obj == null) { | ||
return obj; | ||
} | ||
|
||
let virtualsForChildren = virtuals; | ||
let toApply = null; | ||
|
||
if (Array.isArray(virtuals)) { | ||
virtualsForChildren = []; | ||
toApply = []; | ||
for (const virtual of virtuals) { | ||
if (virtual.length === 1) { | ||
toApply.push(virtual[0]); | ||
} else { | ||
virtualsForChildren.push(virtual); | ||
} | ||
} | ||
} | ||
|
||
applyVirtualsToChildren(schema, obj, virtualsForChildren); | ||
return applyVirtualsToDoc(schema, obj, toApply); | ||
} | ||
|
||
/** | ||
* Apply virtuals to any subdocuments | ||
* | ||
* @param {Schema} schema subdocument schema | ||
* @param {Object} res subdocument | ||
* @param {Array<String>} [virtuals] optional whitelist of virtuals to apply | ||
*/ | ||
|
||
function applyVirtualsToChildren(schema, res, virtuals) { | ||
let attachedVirtuals = false; | ||
for (const childSchema of schema.childSchemas) { | ||
const _path = childSchema.model.path; | ||
const _schema = childSchema.schema; | ||
if (!_path) { | ||
continue; | ||
} | ||
const _obj = mpath.get(_path, res); | ||
if (_obj == null || (Array.isArray(_obj) && _obj.flat(Infinity).length === 0)) { | ||
continue; | ||
} | ||
|
||
let virtualsForChild = null; | ||
if (Array.isArray(virtuals)) { | ||
virtualsForChild = []; | ||
for (const virtual of virtuals) { | ||
if (virtual[0] == _path) { | ||
virtualsForChild.push(virtual.slice(1)); | ||
} | ||
} | ||
|
||
if (virtualsForChild.length === 0) { | ||
continue; | ||
} | ||
} | ||
|
||
applyVirtuals(_schema, _obj, virtualsForChild); | ||
attachedVirtuals = true; | ||
} | ||
|
||
if (virtuals && virtuals.length && !attachedVirtuals) { | ||
applyVirtualsToDoc(schema, res, virtuals); | ||
} | ||
} | ||
|
||
/** | ||
* Apply virtuals to a given document. Does not apply virtuals to subdocuments: use `applyVirtualsToChildren` instead | ||
* | ||
* @param {Schema} schema | ||
* @param {Object} doc | ||
* @param {Array<String>} [virtuals] optional whitelist of virtuals to apply | ||
* @returns | ||
*/ | ||
|
||
function applyVirtualsToDoc(schema, obj, virtuals) { | ||
if (obj == null || typeof obj !== 'object') { | ||
return; | ||
} | ||
if (Array.isArray(obj)) { | ||
for (const el of obj) { | ||
applyVirtualsToDoc(schema, el, virtuals); | ||
} | ||
return; | ||
} | ||
|
||
if (schema.discriminators && Object.keys(schema.discriminators).length > 0) { | ||
for (const discriminatorKey of Object.keys(schema.discriminators)) { | ||
const discriminator = schema.discriminators[discriminatorKey]; | ||
const key = discriminator.discriminatorMapping.key; | ||
const value = discriminator.discriminatorMapping.value; | ||
if (obj[key] == value) { | ||
schema = discriminator; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if (virtuals == null) { | ||
virtuals = Object.keys(schema.virtuals); | ||
} | ||
for (const virtual of virtuals) { | ||
if (schema.virtuals[virtual] == null) { | ||
continue; | ||
} | ||
const virtualType = schema.virtuals[virtual]; | ||
const sp = Array.isArray(virtual) | ||
? virtual | ||
: virtual.indexOf('.') === -1 | ||
? [virtual] | ||
: virtual.split('.'); | ||
let cur = obj; | ||
for (let i = 0; i < sp.length - 1; ++i) { | ||
cur[sp[i]] = sp[i] in cur ? cur[sp[i]] : {}; | ||
cur = cur[sp[i]]; | ||
} | ||
let val = virtualType.applyGetters(cur[sp[sp.length - 1]], obj); | ||
const isPopulateVirtual = | ||
virtualType.options && (virtualType.options.ref || virtualType.options.refPath); | ||
if (isPopulateVirtual && val === undefined) { | ||
if (virtualType.options.justOne) { | ||
val = null; | ||
} else { | ||
val = []; | ||
} | ||
} | ||
cur[sp[sp.length - 1]] = val; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.