使用Mongoose保存文档前为每个对象生成ObjectID

4
我想为数组中的每个对象生成一个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({})
}) 

希望有人已经做过类似的事情,并找到了完美的解决方案!
2个回答

4
如果您想自动添加ObjectId,您需要为其定义一个单独的模式,并将架构的_id选项设置为true。
请按照以下步骤操作:
  • 将您的productsSchema更改为CatalogueSchema(以方便理解)。
  • 为Product(allProducts元素)定义一个新的ProductSchema
  • CatalogueSchema中将allProducts类型定义为[Product.schema]。这将自动添加_idObjectId)。
当您将timestamps选项设置为true时,您也无需将created_atupdated_at添加为架构的一部分。 Catalogue Schema
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中? - Octavian Lojnita
1
在不同的模块中创建单独的 CatalogueSchemaProductSchema。确保您在 CatalogueSchema 中导入了 ProductSchema。我已添加了向目录添加产品的代码。 - Santanu Biswas
哇,那真的有效。非常感谢你,Santanu! - Octavian Lojnita
1
很高兴能够帮助! - Santanu Biswas

0

如果要将多个文档添加到Mongo中,可以使用db.collection.insert()

在Mongoose中,您可以使用Model.insertMany()

请记住,在Mongoose中,当您在一个文档中嵌套另一个文档时,它们实际上并没有像Mongo中那样存储。Mongo仅存储子文档的ID,而不是它们的内容在父文档中 - 甚至没有关于这些ID属于哪个集合的任何信息。

当您使用population时,Mongoose会从Mongo中分别检索相关文档。因此,population是Mongoose的概念。Mongo只存储ID,因此您需要先创建文档,然后才能插入ID。

如果不使用Mongoose,则可以轻松完成您要尝试的事情。如果您愿意,可以使用自己的ID在Mongo中一次请求中存储多个文档,并在另一个请求中将另一个文档与这些ID的数组一起存储。

当然,无论如何进行操作,由于Mongo不支持事务,您都将获得不一致的状态。


我尝试使用insertMany,但它不会生成ObjectID。如果我尝试通过在不同的Schema中生成产品并使用.find来查询它们的另一种方式。在批处理过程中,这是否比将一个文档放在另一个文档中慢一些? - Octavian Lojnita

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接