New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Converting all ObjectIds into string by using Document.toObject() method? #2790
Comments
I've got the same bug. Both |
This is by design right now, because ObjectIds technically aren't strings. Off the top of my head the only way I can think of would be to |
so, function |
by the way, what is the difference between |
Yeah date should still be a date, not a string, after
|
@vkarpov15 Sorry for commenting on a closed issue, but it seemed the most relevant place to post, since it's directly related to this issue. I'm trying to deep-compare two mongoose docs to get a diff object of the changes between them. The only way I've been able to do it so far, is to do this:
That seems like an expensive way of getting a diff between objects. |
Not sure how deep diff works but it might be running into some issues with mongodb ObjectIds. Try converting _id and other objectid fields to strings. Or just use lodash's deep equality check, I think that one works with ObjectIds |
@vkarpov15 deep diff uses lodash for the equality check, so unfortunately that won't work: Converting all ObjectId's to strings would work, but since the objects can contain arrays and/or other nested objects, that becomes quite an expensive task to do aswell.. :/ |
So here's another question, are you using deep-diff on 2 mongoose documents or 2 documents that are the result of |
@vkarpov15 it's usually 1 mongoose doc (converted to a javscript object with .toObject) and one regular javascript object. |
Yeah in that case you're going to need to do |
var transformProps = require('transform-props');
function castToString(arg) {
return String(arg);
}
var doc = new MongooseModel({ subDoc: { foo: 'bar' }});
var docObj = doc.toObject();
transformProps(docObj, castToString, '_id');
console.log(typeof docObj._id); // 'string'
console.log(typeof docObj.subDoc._id); // 'string' |
This feature of Mongo is really regrettable |
@ZacharyRSmith Then what's about other props, eg. author_id(ObjectId refers to User Model)/author_ids(array of ObjectIds)? |
@flight9 you can tell transformProps() to look for multiple keys. see this test here: https://github.com/ZacharyRSmith/transform-props/blob/master/index.test.js#L67 i believe you can get what you want with this: function myToString(val) {
if (Array.isArray(val)) {
return val.map(item => String(item));
}
return String(val);
}
transformProps(obj, myToString, ['author_id', 'author_ids']); |
@ZacharyRSmith Thanks for your solution, It's great! I think i missed one important thing: I don't konw which fields are ObjectId beforehand, because the tool I'm writing should be applied to all models in our project, which may have several ObjectId fields or have none, and its field names are indeterminate. const ObjectID = require('mongodb').ObjectID;
/**
* Convert ObjectId field values inside an object to String type values
* (includes array of ObjectIds and nested ObjectId fields)
* @param obj Object - The Object to be converted.
* @return none
*/
function objectIdtoString(obj) {
for(let k in obj) {
let v = obj[k];
if(typeof v == 'object') {
if(k.endsWith('_id') && v instanceof ObjectID) {
obj[k] = v.toString();
}
else if(
k.endsWith('_ids') && Array.isArray(v) &&
v.length > 0 && v[0] instanceof ObjectID
) {
let vs = [];
for(let iv of v) {
vs.push(iv.toString());
}
obj[k] = vs;
}
else {
objectIdtoString(v);
}
}
}
}
// Call example
objectIdtoString(obj): |
tldr; |
You should also be able to do |
So, here is 2019. |
mongoose.ObjectId.get(v => v.toString()); |
@vkarpov15 looks like this is not a solution when using 'lean'. Or possibly a lean plugin: https://www.npmjs.com/package/mongoose-lean-objectid-string |
@nhitchins correct, you'd have to use a plugin like mongoose-lean-getters. |
@vkarpov15 is this also supposed to work with a discriminator schema? I have a base schema from which I create variants. I tried setting getters on the base schema. I use lean() and used mongoose-lean-getters but I couldn't get this to work. |
@pwrnrd can you please open a new issue and follow the issue template? It should work fine with a discriminator schema. |
Google took me here with “javascript recursive convert of ObjectId to string” function recurisveObjectIdStringifyer(o) {
if (typeof o == 'object' && o != null) {
if (o instanceof Bson.ObjectId) {
o = o.toString();
} else if (Array.isArray(o)) {
for (const k in o) {
o[k] = recurisveObjectIdStringifyer(o[k]);
}
} else {
for (const k of Object.keys(o)) {
o[k] = recurisveObjectIdStringifyer(o[k]);
}
}
}
return o;
}; TESTconsole.log(recurisveObjectIdStringifyer({
one: 1,
two: null,
three: 'string',
four: new Bson.ObjectId('631f0cddb2bc5192fae9da97'),
five: {
one: 1,
two: null,
three: 'string',
four: new Bson.ObjectId('631f0cddb2bc5192fae9da97')
},
six: [{
one: 1,
two: null,
three: 'string',
four: new Bson.ObjectId('631f0cddb2bc5192fae9da97'),
five: {
one: 1,
two: null,
three: 'string',
four: new Bson.ObjectId('631f0cddb2bc5192fae9da97')
}
}, {
one: 1,
two: null,
three: 'string',
four: new Bson.ObjectId('631f0cddb2bc5192fae9da97'),
five: {
one: 1,
two: null,
three: 'string',
four: new Bson.ObjectId('631f0cddb2bc5192fae9da97')
}
}]
})); |
As I found that the
_id
in the document is still an ObjectId after toObject()Is there a way to achieve this?
The text was updated successfully, but these errors were encountered: