Mongoose - 在保存文档之前为每个对象生成 ObjectID
Posted
技术标签:
【中文标题】Mongoose - 在保存文档之前为每个对象生成 ObjectID【英文标题】:Mongoose - Generate ObjectID for each object before saving document 【发布时间】:2017-05-28 07:10:22 【问题描述】:我想为数组中存在的每个对象生成一个 ObjectID。问题是我从另一台服务器获取带有 .forEach 语句的产品,并将它们推送到我的数组中,而没有生成 ObjectID 的模式......
产品架构:
const productsSchema = new mongoose.Schema(
apiKey: String,
domain: String,
totalcount: Number,
totaldone: Number,
allSKUS: Array,
allProducts: Array,
created_at: type: Date ,
updated_at: type: Date ,
, collection: 'products', timestamps: true );
productsSchema.plugin(uniqueValidator);
const Products = mongoose.model('Products', productsSchema);
module.exports = Products;
我的代码:
const newProduct =
apiKey: userApiProducts.apiKey,
domain: userApiProducts.domain,
totalcount: userApiProducts.totalcount,
totaldone: userApiProducts.totaldone,
allSKUS: userApiProducts.allSKUS,
allProducts: userApiProducts.allProducts // generate ObjectID for each object that gets pushed inside the Array
;
Products.findOneAndUpdate( userApiProducts.domain, newProduct, upsert:true , (err, existingProducts) =>
if (err) return next(err);
);
输出:
// Please Check ADD OBJECT ID HERE comment. This is where i want to generate an unique ObjectID before I push the data. I tried with var id = mongoose.Types.ObjectId(); but i'm afraid it will not be Unique...
"_id" : ObjectId("58780a2c8d94cf6a32cd7530"),
"domain" : "http://example.com",
"updatedAt" : ISODate("2017-01-12T23:27:15.465Z"),
"apiKey" : "nf4fh3attn5ygkq1t",
"totalcount" : 11,
"totaldone" : 11,
"allSKUS" : [
"Primul",
"Al doilea",
"Al treilea"
],
"allProducts" : [
// ADD OBJECT ID HERE
"id": 1,
"sku": "Primul",
"name": "Primul",
"status": 1,
"total_images": 2,
"media_gallery_entries": [
"id": 1,
"media_type": "image",
"label": null,
"position": 1,
"disabled": false,
"types": [
"image",
"small_image",
"thumbnail",
"swatch_image"
],
"file": "/g/r/grafolio_angel_and_devil.png"
,
"id": 2,
"media_type": "image",
"label": null,
"position": 2,
"disabled": false,
"types": [],
"file": "/g/r/grafolio_angel_and_devil_thumbnail.jpg"
]
,
// ADD OBJECT ID HERE
"id": 3,
"sku": "Al doilea",
"name": "Al doilea",
"status": 1,
"total_images": 2,
"media_gallery_entries": [
"id": 4,
"media_type": "image",
"label": null,
"position": 2,
"disabled": false,
"types": [],
"file": "/g/r/grafolio_angel_and_devil_thumbnail_1.jpg"
,
"id": 5,
"media_type": "image",
"label": null,
"position": 3,
"disabled": false,
"types": [],
"file": "/b/e/before.png"
]
, etc ......
],
"__v" : 0,
"createdAt" : ISODate("2017-01-12T22:58:52.524Z")
有什么方法可以做到这一点而不必进行大量的数据库调用?我无法想象像这样保存
array.forEach((x)=>
Products.save()
)
希望有人已经研究过类似的东西并找到了完美的解决方案!
【问题讨论】:
【参考方案1】:要将多个文档添加到 Mongo 中,您可以使用 db.collection.insert()
:
在 Mongoose 中,您可以使用 Model.insertMany()
:
但请记住,当您在 Mongoose 中的另一个文档中包含一个文档时,它们实际上并没有像 Mongo 中那样存储。 Mongo 只存储子文档的 ID,而不是它们在父文档中的内容 - 甚至没有关于这些 ID 属于哪个集合的任何信息。
当您使用人口时,Mongoose 实际上会在对 Mongo 的单独请求中从数据库中检索相关文档。所以,人口是猫鼬的一个概念。 Mongo 只存储 ID,因此您需要先创建文档,然后才能插入 ID。
如果不使用 Mongoose,您尝试做的事情会很容易。如果需要,您可以使用自己的 ID 在 Mongo 的一个请求中存储多个文档,并且可以在另一个请求中存储具有这些 ID 数组的另一个文档。
当然,无论如何你都会在操作过程中得到不一致的状态,因为 Mongo 不支持事务。
【讨论】:
我尝试了 insertMany,但它没有生成 ObjectID。如果我以另一种方式尝试通过在不同的架构中生成产品并使用 .find 来查询它们。在批处理过程中,这会比在另一个文档中包含一个文档要慢一些吗?【参考方案2】:如果要自动添加ObjectId
,则需要为其定义单独的架构,并将架构的_id
选项设置为true。
执行以下操作:
将您的productsSchema
更改为 CatalogueSchema
(为了便于
理解)。
为 Product(allProducts 的元素)定义一个新的 ProductSchema
在CatalogueSchema
中将所有产品类型定义为[Product.schema]
。这将自动添加_id
(ObjectId
)。
此外,当您将时间戳选项设置为 true 时,您不需要添加 created_at
和 updated_at
作为架构的一部分。
目录架构
const Product = require('Product_Schema_Module_Path'); // Edit
const CatalogueSchema = new mongoose.Schema(
apiKey: String,
domain: String,
totalcount: Number,
totaldone: Number,
allSKUS: Array,
allProducts: [Product.schema]
// Note the change here (Array -> [Product.schema]
// Creating a separate schema ensures automatic id (ObjectId)
, collection: 'catalogue', timestamps: true );
CatalogueSchema.plugin(uniqueValidator);
const Catalogue = mongoose.model('Catalogue', CatalogueSchema);
module.exports = Catalogue;
产品架构 (确保添加 ObjectId 的新架构)
const ProductSchema = new mongoose.Schema(
id: Number,
sku: String,
name: String,
status: Number,
total_images: Number,
media_gallery_entries: Array
, _id: true, timestamps: true );
// _id option is true by default. You can ommit it.
// If _id is set to false, it will not add ObjectId
ProductSchema.plugin(uniqueValidator);
const Product = mongoose.model('Product', ProductSchema);
module.exports = Product;
编辑(将产品保存在目录中)
(另外,请注意,您必须在 CatalogueSchema 模块中要求 ProductSchema 模块)
// Map userApiProducts.allProducts to array of Product documents
const products = userApiProducts.allProducts.map(product =>
return new Product(product);
)
const newProduct =
apiKey: userApiProducts.apiKey,
domain: userApiProducts.domain,
totalcount: userApiProducts.totalcount,
totaldone: userApiProducts.totaldone,
allSKUS: userApiProducts.allSKUS,
allProducts: products
;
Catalogue
.findOneAndUpdate( domain: userApiProducts.domain , newProduct, upsert:true , (err, products) =>
// Handle error
);
【讨论】:
用你的方法我得到 [Product.schema] 是未定义的。你能告诉我你如何将 ProductsSchema 模型保存在 CatalogueSchema 中吗? 在单独的模块中创建单独的CatalogueSchema
和 ProductSchema
。确保将ProductSchema
导入CatalogueSchema
。我已经添加了将产品添加到目录的代码。
哇,这确实有效。非常感谢桑塔努!
很高兴能帮上忙!以上是关于Mongoose - 在保存文档之前为每个对象生成 ObjectID的主要内容,如果未能解决你的问题,请参考以下文章
通过 mongoose 为 mongodb 中集合的文档中的每个嵌套对象创建 ID