-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🐛 Don't flatten objects when updating records, it causes too many issues
- Loading branch information
Showing
3 changed files
with
101 additions
and
74 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -131,7 +131,11 @@ Mongo.setMethod(function castToBigInt(value) { | |
} | ||
|
||
if (typeof value == 'object') { | ||
return value.toBigInt(); | ||
if (value.toBigInt) { | ||
return value.toBigInt(); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
return BigInt(value); | ||
|
@@ -541,110 +545,125 @@ Mongo.setMethod(function _create(context) { | |
*/ | ||
Mongo.setMethod(function _update(context) { | ||
|
||
const model = context.getModel(), | ||
options = context.getSaveOptions(); | ||
const model = context.getModel(); | ||
|
||
return Swift.waterfall( | ||
this.collection(model.table), | ||
collection => { | ||
return performUpdate(collection, model, context); | ||
} | ||
); | ||
}); | ||
|
||
let key; | ||
/** | ||
* Perform the update | ||
* | ||
* @author Jelle De Loecker <[email protected]> | ||
* @since 1.4.0 | ||
* @version 1.4.0 | ||
* | ||
* @return {Pledge} | ||
*/ | ||
const performUpdate = (collection, model, context) => { | ||
|
||
// Get the converted data | ||
const data = context.getConvertedData(); | ||
const options = context.getSaveOptions(); | ||
|
||
// Get the id to update, it should always be inside the given data | ||
let id = data._id; | ||
let key; | ||
|
||
// Clone the data object | ||
let doc = {...data}; | ||
// Get the converted data | ||
const data = context.getConvertedData(); | ||
|
||
// Values that will get flattened | ||
let to_flatten = {}; | ||
// Get the id to update, it should always be inside the given data | ||
let id = data._id; | ||
|
||
// Field names that won't get flattened | ||
let no_flatten = {}; | ||
// Clone the data object | ||
let doc = {...data}; | ||
|
||
// Remove the id | ||
delete doc._id; | ||
// Values that will get flattened | ||
let to_flatten = {}; | ||
|
||
if (!options.override_created) { | ||
delete doc.created; | ||
} | ||
// Field names that won't get flattened | ||
let no_flatten = {}; | ||
|
||
// Iterate over the fields | ||
for (key in doc) { | ||
let field = model.getField(key); | ||
// Remove the id | ||
delete doc._id; | ||
|
||
if (field && (field.is_self_contained || field.is_translatable)) { | ||
no_flatten[key] = doc[key]; | ||
} else { | ||
to_flatten[key] = doc[key]; | ||
} | ||
} | ||
if (!options.override_created) { | ||
delete doc.created; | ||
} | ||
|
||
// Flatten the object, using periods & NOT flattening arrays | ||
let flat = Object.flatten(to_flatten, '.', false); | ||
// Iterate over the fields | ||
for (key in doc) { | ||
let field = model.getField(key); | ||
|
||
// Assign the no-flatten values, too | ||
Object.assign(flat, no_flatten); | ||
if (field && (field.is_self_contained || field.is_translatable || typeof doc[key] == 'object')) { | ||
no_flatten[key] = doc[key]; | ||
} else { | ||
to_flatten[key] = doc[key]; | ||
} | ||
} | ||
|
||
let unset = {}; | ||
// Flatten the object, using periods & NOT flattening arrays | ||
let flat = Object.flatten(to_flatten, '.', false); | ||
|
||
for (key in flat) { | ||
// Undefined or null means we want to delete the value | ||
// We can't set null, because that could interfere with dot notation updates | ||
if (flat[key] == null) { | ||
// Assign the no-flatten values, too | ||
Object.assign(flat, no_flatten); | ||
|
||
// Add the key to the unset object | ||
unset[key] = ''; | ||
let unset = {}; | ||
|
||
// Remove it from the flat object | ||
delete flat[key]; | ||
} | ||
} | ||
for (key in flat) { | ||
// Undefined or null means we want to delete the value | ||
// We can't set null, because that could interfere with dot notation updates | ||
if (flat[key] == null) { | ||
|
||
let update_object = { | ||
$set: flat | ||
}; | ||
// Add the key to the unset object | ||
unset[key] = ''; | ||
|
||
if (!Object.isEmpty(unset)) { | ||
update_object.$unset = unset; | ||
} | ||
// Remove it from the flat object | ||
delete flat[key]; | ||
} | ||
} | ||
|
||
if (options.debug) { | ||
console.log('Updating with obj', id, update_object); | ||
} | ||
let update_object = { | ||
$set: flat | ||
}; | ||
|
||
let promise; | ||
if (!Object.isEmpty(unset)) { | ||
update_object.$unset = unset; | ||
} | ||
|
||
if (collection.findOneAndUpdate) { | ||
promise = collection.findOneAndUpdate({_id: id}, update_object, {upsert: true}); | ||
} else if (collection.findAndModify) { | ||
promise = collection.findAndModify({_id: id}, [['_id', 1]], update_object, {upsert: true}); | ||
} else { | ||
// If it's not available (like nedb) | ||
promise = collection.update({_id: ''+id}, update_object, {upsert: true}); | ||
} | ||
if (options.debug) { | ||
console.log('Updating with obj', id, update_object); | ||
} | ||
|
||
let pledge = new Swift(); | ||
let promise; | ||
|
||
Pledge.done(promise, function afterUpdate(err, result) { | ||
if (collection.findOneAndUpdate) { | ||
promise = collection.findOneAndUpdate({_id: id}, update_object, {upsert: true}); | ||
} else if (collection.findAndModify) { | ||
promise = collection.findAndModify({_id: id}, [['_id', 1]], update_object, {upsert: true}); | ||
} else { | ||
// If it's not available (like nedb) | ||
promise = collection.update({_id: ''+id}, update_object, {upsert: true}); | ||
} | ||
|
||
// Clear the cache | ||
model.nukeCache(); | ||
let pledge = new Swift(); | ||
|
||
if (err != null) { | ||
return pledge.reject(err); | ||
} | ||
Pledge.done(promise, function afterUpdate(err, result) { | ||
|
||
pledge.resolve(Object.assign({}, data)); | ||
}); | ||
// Clear the cache | ||
model.nukeCache(); | ||
|
||
return pledge; | ||
if (err != null) { | ||
return pledge.reject(err); | ||
} | ||
); | ||
}); | ||
|
||
pledge.resolve(Object.assign({}, data)); | ||
}); | ||
|
||
return pledge; | ||
|
||
}; | ||
|
||
/** | ||
* Remove a record from the database | ||
|
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 |
---|---|---|
@@ -1,7 +1,7 @@ | ||
{ | ||
"name": "alchemymvc", | ||
"description": "MVC framework for Node.js", | ||
"version": "1.4.0-alpha.5", | ||
"version": "1.4.0-alpha.6", | ||
"author": "Jelle De Loecker <[email protected]>", | ||
"keywords": [ | ||
"alchemy", | ||
|