我发现文档中的_id
在 toObject() 之后仍然是一个 ObjectId
有没有办法做到这一点?
我有同样的错误。 toJSON()
和toObject()
都不会对ObjectId
实例进行字符串化。
现在这是设计使然,因为 ObjectId 在技术上不是字符串。 在我的脑海中,我能想到的唯一方法是JSON.parse(JSON.stringify(doc));
您对所有对象 ID 进行字符串化的用例是什么?
那么,函数toJSON()
不会将对象转换为 JSON 字符串吗? _id 和日期不是字符串而是对象?
顺便问一下, toObject()
和toJSON()
有什么区别?
谢谢!
是的,在toJSON()
+ toObject()
之后,日期仍然应该是一个日期,而不是一个字符串。
toJSON()
和toObject()
本质上是相同的,唯一的区别是当你做JSON.stringify(doc)
JavaScript 在 doc 上查找toJSON()
函数并使用它来转换目的。 所以toJSON()
JSON.stringify()
语法糖。
@vkarpov15很抱歉对已关闭的问题发表评论,但它似乎是最相关的发布位置,因为它与此问题直接相关。
我正在尝试深入比较两个猫鼬文档以获取它们之间更改的差异对象。
然而,ObjectID 似乎不能直接比较,因为它们总是以差异结尾,即使它们包含完全相同的 id。
到目前为止,我能够做到的唯一方法就是这样做:
var objectdiff = require('object-deep-diff');
var diffresult = objectdiff(
JSON.parse(JSON.stringify(doc1.toObject())),
JSON.parse(JSON.stringify(doc2.toObject()))
);
这似乎是一种获取对象之间差异的昂贵方法。
您知道可靠比较猫鼬文档的更好方法吗?
不确定深度差异的工作原理,但它可能会遇到 mongodb ObjectIds 的一些问题。 尝试将 _id 和其他 objectid 字段转换为字符串。 或者只是使用 lodash 的深度相等检查,我认为可以使用 ObjectIds
@vkarpov15 deep diff 使用 lodash 进行相等性检查,所以很遗憾这不起作用:
https://github.com/rbs392/object-deep-diff/blob/master/index.js
将所有 ObjectId 转换为字符串是可行的,但由于对象可以包含数组和/或其他嵌套对象,这也成为一项非常昂贵的任务......:/
所以这是另一个问题,您是在 2 个 mongoose 文档还是 2 个toObject()
结果的文档上使用深度差异? 后者应该工作,前者没有那么多。
@vkarpov15通常是 1 个 mongoose 文档(使用 .toObject 转换为 javscript 对象)和一个常规 javascript 对象。
原因是我需要将来自客户端的数据与数据库中已有的数据进行比较。
因此,来自客户端的数据已经转换了 ObjectID,但来自数据库的数据没有。
但由于我在 mongoose 插件中进行这种深度差异检查,我需要绝对确保两个文档的构造相同,所以这就是为什么我必须运行 JSON.parse(JSON.stringify(doc.toObject()) ) 在两个文档上。
是的,在这种情况下,您将需要执行JSON.parse(JSON.stringify())
,这是将所有对象 ID 转换为字符串的最简单方法。
JSON.parse(JSON.stringify())
对我来说计算量太大,所以我不得不创建这个 perf-thinking lib 。
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'
Mongo的这个特性真的很遗憾
@ZacharyRSmith那么其他道具呢,例如。 author_id(ObjectId 指的是用户模型)/author_ids(ObjectIds 数组)?
@flight9您可以告诉 transformProps() 查找多个键。 在这里看到这个测试: https ://github.com/ZacharyRSmith/transform-props/blob/master/index.test.js#L67
我相信你可以得到你想要的:
function myToString(val) {
if (Array.isArray(val)) {
return val.map(item => String(item));
}
return String(val);
}
transformProps(obj, myToString, ['author_id', 'author_ids']);
@ZacharyRSmith感谢您的解决方案,太好了!
我想我错过了一件重要的事情:我事先不知道哪些字段是 ObjectId,因为我正在编写的工具应该应用于我们项目中的所有模型,这些模型可能有多个 ObjectId 字段或没有,以及它的字段名称是不确定的。
所以经过几个小时的尝试,我有我的解决方案:
const ObjectID = require('mongodb').ObjectID;
/**
* Convert ObjectId field values inside an object to String type values
* (includes array of ObjectIds and nested ObjectId fields)
* <strong i="9">@param</strong> obj Object - The Object to be converted.
* <strong i="10">@return</strong> 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):
@vkarpov15
是的,在这种情况下,您将需要执行 JSON.parse(JSON.stringify()),这是将所有对象 ID 转换为字符串的最简单方法。
tldr; JSON.parse(JSON.stringify())
是一个同步的阻塞任务,可能会导致严重的瓶颈。 这不应该是这个问题的接受/建议的解决方案......
你也应该能够做到mongoose.Types.ObjectId.prototype.toJSON = function() { return this.toString();
。 但即使那篇文章说,JSON.parse(JSON.stringify) 是进行深度克隆的更快方法之一,他们的问题是他们重复不必要的深度克隆
所以,这里是 2019 年。
我们是否还有从对象上的每个 ObjectId 实例获取十六进制字符串的好方法?
@gitowiec
mongoose.ObjectId.get(v => v.toString());
请参阅: http ://thecodebarbarian.com/whats-new-in-mongoose-54-global-schematype-configuration.html#schematype -getters
@vkarpov15看起来这不是使用“精益”时的解决方案。
因此,如果想要的结果是返回一个带有字符串 objectIds 的普通 json 对象,那么实现这一点的最有效方法似乎是仍然使用JSON.parse(JSON.stringify())
和lean
选项。
或者可能是一个精益插件: https ://www.npmjs.com/package/mongoose-lean-objectid-string
@nhitchins正确,您必须使用像 mongoose -lean-getters这样的插件。
@vkarpov15这也应该与鉴别器模式一起使用吗? 我有一个基本架构,我从中创建变体。 我尝试在基本架构上设置吸气剂。 我使用了 lean() 并使用了 mongoose-lean-getters,但我无法让它工作。
@pwrnrd你能打开一个新问题并遵循问题模板吗? 它应该与鉴别器模式一起正常工作。
最有用的评论
Mongo的这个特性真的很遗憾