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

Kho*_*hon 23 mongoose mongodb node.js

有没有办法在mongoose中声明一个Model模式,这样当模型新建时,_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);
Run Code Online (Sandbox Code Playgroud)

起初,我觉得很棒!,我会做的

_id:    {type:ObjectIdSchema, default: new ObjectId()}
Run Code Online (Sandbox Code Playgroud)

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

那么有没有办法做到这一点,每次我做"new Person()"生成一个新的ObjectId()?

我试图这样做的原因是因为我需要知道新人的_id值的价值以便进一步处理.

我也尝试过:

var person = new Person({firstName: "Joe", lastName: "Baz"});
person.save(function(err, doc, num){
    console.log(doc._id);
});
Run Code Online (Sandbox Code Playgroud)

即使这样,doc也不包含ObjectId.但如果我查看数据库,它确实包含它.

ps我正在使用mongoose 2.7.1

pps我知道我可以在创建人时手动创建ObjectId:

var person = new Person({_id: new ObjectId(), firstName: "Joe", lastName: "Baz"});
Run Code Online (Sandbox Code Playgroud)

但我宁愿不必导入ObjectId,每次我想要新建一个Person时都必须新建它.我以前习惯使用mongodb的java驱动程序,我可以在模型构造函数中为_id字段创建值.

Las*_*ios 25

你调用var person = new Person(); person._id应该给你id(即使它尚未保存).只是实例化它就足以给它一个id.你仍然可以保存它,并且它将存储id以及person对象的其余部分

  • 是的,并且不需要在架构中包含`_id`字段. (3认同)
  • @JohnnyHK,你和Last Rose Studios是对的.就像你说的那样.我注释掉了"_id:ObjectIdSchema"这一行,当我新买的Person()时它有了id!但是当我没有评论出来时,id从未生成过.多谢你们!非常感激. (2认同)
  • 对于新观众来说,这种行为自从改变了吗?今天我被迫提到`default:new mongoose.Types.ObjectId()`如果我在模型模式中添加了`_id`就没有它! (2认同)

yis*_*aiz 21

添加auto标志:

_id: {
    type: mongoose.Schema.Types.ObjectId,
    index: true,
    required: true,
    auto: true,
  }
Run Code Online (Sandbox Code Playgroud)

资源

  • 无需显式指定 `_id`:`在 MongoDB 中,存储在集合中的每个文档都需要一个唯一的 _id 字段作为主键。如果插入的文档省略了 _id 字段,MongoDB 驱动程序会自动为 _id 字段生成一个 ObjectId。`。[阅读文档](https://docs.mongodb.com/manual/reference/bson-types/#objectid) (3认同)

小智 10

代替:

_id:    {type:ObjectIdSchema, default: new ObjectId()}
Run Code Online (Sandbox Code Playgroud)

你应该做:

_id:    {type:ObjectIdSchema, default: function () { return new ObjectId()} }
Run Code Online (Sandbox Code Playgroud)

  • 这是不必要的......如果你没有指定_id是什么,它默认为ObjectId并自己创建 (7认同)
  • 这个答案仍然有用,因为例如子文档没有自动生成的 _id (3认同)

use*_*800 9

摘自官方 MongoDB 手册和文档:

_ID

每个 MongoDB 文档中都需要的字段。该_id字段必须具有唯一值。您可以将该_id字段视为文档的主键。如果您创建一个没有_id字段的新文档,MongoDB 会自动创建该字段并分配一个唯一的 BSON ObjectId。
来源


对象ID

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

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

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

MongoDB 客户端应该添加一个_id具有唯一ObjectId的字段。将 ObjectIds 用于_id字段提供了以下额外好处:在 mongo shell 中,您可以使用方法访问ObjectId的创建时间 ObjectId.getTimestamp()。对存储 ObjectId 值的 _id 字段进行排序大致相当于按创建时间排序。

重要
虽然ObjectId值应该随着时间的推移而增加,但它们不一定是单调的。这是因为他们:

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

明确声明_id

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

new Schema({ _id: { type: Schema.ObjectId, auto: true }})
Run Code Online (Sandbox Code Playgroud)

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


TL; 博士

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

  • 这是确切的答案,也是唯一有效的方法。谢谢 (4认同)