Sails 和子文档 ObjectId()
Sails and subdocument ObjectId()
我有一个现有的 MongoDB 集合,基本上看起来像这样:
users: [
{
"_id": ObjectId("56a6f714a2c56f1c3b0f17f1"),
"name": "Daniel",
"phones" : [
{
"_id": ObjectId(""56a78dd1879c40ea63822141"),
"areacode": 333,
"number": 111111111
},
{
"_id": ObjectId(""56a78dd1879c40ea63822141"),
"areacode": 111,
"number": 99999999
}
]
},
{
"_id": ObjectId("56a6f714a2c56f1c3b0f17f1"),
"name": "John",
"phones" : [
{
"_id": ObjectId(""56a78dd1879c40ea63822141"),
"areacode": 333,
"number": 111111111
},
{
"_id": ObjectId(""56a78dd1879c40ea63822141"),
"areacode": 111,
"number": 99999999
}
]
}
]
如您所见,我在子文档中使用对象 ID 将此数据与我们存储数字附加信息的外部集合相关联。所有这些 ID 都是由 Mongoose 在其他自动执行此操作的应用程序中自动生成的。
现在,在 Waterline 中,没有对子文档的架构支持,因此在对集合执行 find() 时,子文档 ObjectId 将作为 JSON 而不是 ID 字符串返回。
这样的结果类似于
results: [
{
"id": "56a6f714a2c56f1c3b0f17f1",
"name": "Daniel",
"phones" : [
{
"_id": {
"_bsontype": "ObjectID",
"id": "V§zÐ\u0019}dÒÏ_"
}
"areacode": 333,
"number": 111111111
},
{
"_id": {
"_bsontype": "ObjectID",
"id": "V§zÐ\u0019}dÒÏ_"
}
"areacode": 111,
"number": 99999999
}
]
}
]
Mongoose 优雅地处理了这个问题,您始终可以让这些 ID 可用于在客户端执行相关查询,但是使用 Waterline 并且没有嵌套模式,这似乎是另一个死胡同。
有没有什么方法可以解决这个问题,而无需在返回之前遍历整个集合、迁移数据库、更改文档或规范化数据库?此数据由多个应用访问,需要保持原样。
可能有更好的方法来做到这一点,但最后我决定在返回的 JSON 上递归迭代,用适当的 ObjectID 替换 ID,感谢 bson-objectid 库.
我基本上做的是在模型级别的 toJSON 函数上调用此方法:
// Recursively iterate over a JSON object
function replaceBSONIDs(object){
var ObjectID = require("bson-objectid");
for(var x in object){
if(typeof object[x] == 'object') {
replaceBSONIDs(object[x]);
} else {
// Perform the actual replace of the _id with an object ID
if('_id' in object) {
object.id = ObjectID(object._id.id);
delete object._id
}
}
}
这个问题听起来像是水线错误,所以打开一个问题。希望这对其他人有帮助。
我有一个现有的 MongoDB 集合,基本上看起来像这样:
users: [
{
"_id": ObjectId("56a6f714a2c56f1c3b0f17f1"),
"name": "Daniel",
"phones" : [
{
"_id": ObjectId(""56a78dd1879c40ea63822141"),
"areacode": 333,
"number": 111111111
},
{
"_id": ObjectId(""56a78dd1879c40ea63822141"),
"areacode": 111,
"number": 99999999
}
]
},
{
"_id": ObjectId("56a6f714a2c56f1c3b0f17f1"),
"name": "John",
"phones" : [
{
"_id": ObjectId(""56a78dd1879c40ea63822141"),
"areacode": 333,
"number": 111111111
},
{
"_id": ObjectId(""56a78dd1879c40ea63822141"),
"areacode": 111,
"number": 99999999
}
]
}
]
如您所见,我在子文档中使用对象 ID 将此数据与我们存储数字附加信息的外部集合相关联。所有这些 ID 都是由 Mongoose 在其他自动执行此操作的应用程序中自动生成的。
现在,在 Waterline 中,没有对子文档的架构支持,因此在对集合执行 find() 时,子文档 ObjectId 将作为 JSON 而不是 ID 字符串返回。
这样的结果类似于
results: [
{
"id": "56a6f714a2c56f1c3b0f17f1",
"name": "Daniel",
"phones" : [
{
"_id": {
"_bsontype": "ObjectID",
"id": "V§zÐ\u0019}dÒÏ_"
}
"areacode": 333,
"number": 111111111
},
{
"_id": {
"_bsontype": "ObjectID",
"id": "V§zÐ\u0019}dÒÏ_"
}
"areacode": 111,
"number": 99999999
}
]
}
]
Mongoose 优雅地处理了这个问题,您始终可以让这些 ID 可用于在客户端执行相关查询,但是使用 Waterline 并且没有嵌套模式,这似乎是另一个死胡同。
有没有什么方法可以解决这个问题,而无需在返回之前遍历整个集合、迁移数据库、更改文档或规范化数据库?此数据由多个应用访问,需要保持原样。
可能有更好的方法来做到这一点,但最后我决定在返回的 JSON 上递归迭代,用适当的 ObjectID 替换 ID,感谢 bson-objectid 库.
我基本上做的是在模型级别的 toJSON 函数上调用此方法:
// Recursively iterate over a JSON object
function replaceBSONIDs(object){
var ObjectID = require("bson-objectid");
for(var x in object){
if(typeof object[x] == 'object') {
replaceBSONIDs(object[x]);
} else {
// Perform the actual replace of the _id with an object ID
if('_id' in object) {
object.id = ObjectID(object._id.id);
delete object._id
}
}
}
这个问题听起来像是水线错误,所以打开一个问题。希望这对其他人有帮助。