当猫鼬模型是新的时,有没有办法自动生成 ObjectId?

Posted

技术标签:

【中文标题】当猫鼬模型是新的时,有没有办法自动生成 ObjectId?【英文标题】:is there a way to auto generate ObjectId when a mongoose Model is new'ed? 【发布时间】:2012-07-21 05:45:41 【问题描述】:

有没有办法在 mongoose 中声明模型模式,以便在新模型中自动生成 _id 字段?

例如:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectIdSchema = Schema.ObjectId;
var ObjectId = mongoose.Types.ObjectId;

var PersonSchema = new Schema(
    _id:            ObjectIdSchema,
    firstName:      type: String, default: 'N/A',
    lastName:       type: String, default: 'N/A',
    age:            type: Number, min: 1
);

var Person = mongoose.model('Person', PersonSchema);

一开始,我觉得很棒!,我会做的

_id:    type:ObjectIdSchema, default: new ObjectId()

但这当然不起作用,因为 new ObjectId() 仅在架构初始化时调用。所以调用 new Persion() 两次会创建两个具有相同 _id 值的对象。

那么有没有办法让我每次执行“new Person()”时都会生成一个新的 ObjectId()?

我之所以尝试这样做是因为我需要知道新人的 _id 值的值以进行进一步处理。

我也试过了:

var person = new Person(firstName: "Joe", lastName: "Baz");
person.save(function(err, doc, num)
    console.log(doc._id);
);

即便如此,doc 也不包含 ObjectId。但如果我查看数据库,它确实包含它。

附言我正在使用猫鼬 2.7.1

p.p.s.我知道我可以在创建人时手动创建 ObjectId:

var person = new Person(_id: new ObjectId(), firstName: "Joe", lastName: "Baz");

但我宁愿不必导入 ObjectId 并且每次我想新建一个人时都必须新建它。我猜我习惯使用 mongodb 的 java 驱动程序,我可以在 Model 构造函数中为 _id 字段创建值。

【问题讨论】:

【参考方案1】:

这是一个很好的方法

在模型中:

const schema = new Schema( userCurrencyId:type: mongoose.Schema.Types.ObjectId,
        index: true,
        required: true,
        auto: true);

【讨论】:

【参考方案2】:

取自官方 MongoDB 手册和文档:

_id

每个 MongoDB 文档中都需要一个字段。 _id 字段必须有一个 独特的价值。您可以将_id 字段视为文档的主要字段 钥匙。如果您创建一个没有 _id 字段的新文档,MongoDB 自动创建字段并分配一个唯一的 BSON ObjectId。 Source


对象ID

ObjectId 很小,可能是唯一的,生成速度快,并且是有序的。 ObjectId 值由 12 个字节组成,其中前四个字节是 反映 ObjectId 创建的时间戳。具体来说:

一个 4 字节的值,表示自 Unix 纪元以来的秒数,一个 5 字节的值 随机值和一个 3 字节计数器,以随机值开始。在 MongoDB,存储在集合中的每个文档都需要唯一的_id 充当主键的字段。如果插入的文档省略 _id字段,MongoDB驱动自动生成一个ObjectId 对于_id 字段。

这也适用于通过更新操作插入的文档 upsert:是的。

MongoDB 客户端应添加具有唯一 ObjectId_id 字段。 将 ObjectIds 用于 _id 字段可提供以下附加功能 好处:在mongo shell中,可以访问 ObjectId,使用ObjectId.getTimestamp() 方法。按 _id 排序 存储 ObjectId 值的字段大致相当于排序 创建时间。 重要提示虽然 ObjectId 值应该增加超过 时间,它们不一定是单调的。这是因为他们:

仅包含一秒的时间分辨率,因此 ObjectId 值 在同一秒内创建的顺序没有保证,并且 由可能具有不同系统时钟的客户端生成。 Source

显式声明_id:

当显式声明_id 字段时,指定auto 选项:

new Schema( _id:  type: Schema.ObjectId, auto: true )

仅 ObjectId - 如果 turnOn 为 true,则添加自动生成的 ObjectId 默认值。Source


TL;DR

如果您创建一个没有 _id 字段的新文档,MongoDB 会自动创建该字段并分配一个唯一的 BSON ObjectId。

【讨论】:

这是准确的答案,也是唯一有效的方法。谢谢【参考方案3】:

添加auto 标志:

_id: 
    type: mongoose.Schema.Types.ObjectId,
    index: true,
    required: true,
    auto: true,
  

source

【讨论】:

无需明确指定_idIn MongoDB, each document stored in a collection requires a unique _id field that acts as a primary key. If an inserted document omits the _id field, the MongoDB driver automatically generates an ObjectId for the _id field.。 Read the docs【参考方案4】:

代替:

_id:    type:ObjectIdSchema, default: new ObjectId()

你应该这样做:

_id:    type:ObjectIdSchema, default: function ()  return new ObjectId() 

【讨论】:

这是不必要的......如果你不指定_id是什么,它默认为ObjectId并创建自己 [错误:文档必须有_id才能保存] 这个答案仍然有用,因为例如子文档没有自动生成的_id 这仍然是实际的,尤其是对于 dockerized mongo 图像【参考方案5】:

当你调用 var person = new Person(); person._id 应该为您提供 id(即使尚未保存)。只需实例化它就足以给它一个 id。之后您仍然可以保存它,这将存储 id 以及 person 对象的其余部分

【讨论】:

是的,并且不需要在架构中包含_id 字段。 @JohnnyHK,你和 Last Rose Studios 是对的。就像你说的那样。我注释掉了“_id:ObjectIdSchema”这一行,当我新建 Person() 时,它就有了 id!但是当我没有注释掉它时,id 就永远不会生成。多谢你们!非常感谢。 对于新观众,这种行为自那以后有改变吗?今天我不得不提到default: new mongoose.Types.ObjectId(),如果我在模型架构中添加_id,它就不起作用了! 我可以回显上面的 cmets,使用节点版本 4.8.1 ,如果 _id 在 Schema 中声明,_id 不会自动生成

以上是关于当猫鼬模型是新的时,有没有办法自动生成 ObjectId?的主要内容,如果未能解决你的问题,请参考以下文章

在预保存回调中确定记录是不是“新”

在预保存回调中确定记录是不是“新”

有位高人曾经说过,人到了走投无路的时侯才是新的开始

如何编写猫鼬查询来组合来自两个模型的数据?

猫鼬如何在模型中设置日期格式

如何知道一个模型是不是是新的?