猫鼬不能使用字符串类型填充

猫鼬不能使用字符串类型填充

问题描述:

所以我有这个带有字段的 FacilityPersonnel 模型:

So I have this FacilityPersonnel model with fields :

var field = {
    createdAt: {type: Date, default: Date.now()},
    updatedAt: {type: Date, default: Date.now()},

    some_id: {type: String},
    fooAccessType: {
        type: String, 
        default: 'SuperAdmin', 
        ref: 'AccessType'
    },  
}

我正在尝试在 controller 上使用它populate fooAccessType.

Im trying to populate the fooAccessType using this on controller.

FacilityPersonnel.findOne({_id:req.params.id})
    .populate('fooAccessType')
    .exec(function (err, doc) {
        if (err) { res.status(500).json(err); return; };
        res.status(200).json(doc);
    })

要查询的所有数据都可用,并且当我删除行 .populate('fooAccessType') 时查询正在工作,但如果没有,我将返回此错误:

All data to be queried are all available and the query is working when I removed the line .populate('fooAccessType') but if not I returns this error :

{
    "stack": "Error\n    at MongooseError.CastError ...",
    "message": "Cast to ObjectId failed for value \"SuperAdmin\" at path \"_id\"",
    "name": "CastError",
    "kind": "ObjectId",
    "value": "SuperAdmin",
    "path": "_id"
}

这是为什么?谢谢.

目前,只有引用另一个集合的 _idObjectId 值可以用作 参考.

Currently, only ObjectId values which refer to the _id of another collection can be used as refs.

这里是一个讨论 https://github.com/Automattic/mongoose/issues/2562

但是,这可能是未来的一项改进.

However, it could be one enhancement in the future.

实际上,不需要在populate字段中添加default值,只需定义fooAccessType如下

Actually, it is no need to add default value to populate field, just define the fooAccessType as below

fooAccessType: {
    type: String, 
    ref: 'AccessType'
},  

对于人口

FacilityPersonnel.findOne({_id:req.params.id})
    .populate('fooAccessType')
    .exec(


population中使用了ObjectIDObjectId是一个12字节的BSON类型,使用:


The ObjectID is used in the population, and the ObjectId is a 12-byte BSON type, constructed using:

一个 4 字节的值,表示自 Unix 纪元以来的秒数,

a 4-byte value representing the seconds since the Unix epoch,

一个 3 字节的机器标识符,

a 3-byte machine identifier,

一个 2 字节的进程 ID,和

a 2-byte process id, and

一个 3 字节的计数器,从一个随机值开始.

a 3-byte counter, starting with a random value.

所以SuperAdmin 不是一个正确的ObjectID.您可以使用 UUID 作为 ObjectID

So SuperAdmin is not one correct ObjectID. You could use UUID as the default value of ObjectID

var uuid = require('node-uuid');

// ...
fooAccessType: {
    type: String, 
    default: uuid.v1, 
    ref: 'AccessType'
},  

然而,上面的代码很奇怪,fooAccesType 是对AccessType 文档的引用.

However, the above code is weird, the fooAccesType is reference to AccessType document.

当尝试保存field文档时,应该先保存AccessType,然后从这个保存的AccessType中获取ObjectID 并将其分配给 fooAccessType,最终保存新的 field 文档.

When try to save the field document, the AccessType should be saved firstly, then get the ObjectID from this saved AccessType and assign it to fooAccessType, eventually, save the new field document.

var access = new AccessType({});
access.save(function(err){
   if (err)
      // error handling
   else {
       facilityperson.fooAccessType = access._id;
       facilityperson.save(function(err) {

       });
   }
});

对于人口

FacilityPersonnel.findOne({_id:req.params.id})
    .populate('fooAccessType')
    .exec(