gpt4 book ai didi

javascript - 使用其他字段的数据创建 ID

转载 作者:可可西里 更新时间:2023-11-01 09:50:25 25 4
gpt4 key购买 nike

我是 mongodb 的新手,我正在使用 mongoose 来验证和排序数据(如果这不起作用,我愿意将其更改为 MySQL)。
该应用程序将是一个电子商店,用于购买与电影、游戏等相关的商品。

我的架构如下:

var productSchema = {
id: {
type: String,
required: true
},
name: {
type: String,
required: true
},
img: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
stock: {
type: Number,
required: true
},
category: {
object: {
type: String,
required: true
},
group: {
type: String,
required: true
},
name: {
type: String,
required: true
}
}
};

这就是我想做的:

如果我在类别中有以下数据:
  • category.object = "戒指"
  • category.group = "电影"
  • category.name="指环王"

  • 我希望 id 由类别中每个字段的第一个字母和一个数字(添加的最后一个项目的数字加 1)组成。在这种情况下,它将是 RMLOTR1。

    我现在在做什么

    我同时添加了大量数据,所以每次我这样做时,我都会创建一个函数来遍历添加的所有项目并执行我想要的操作,但是......

    我的问题是

    是否有内置的方法可以使用 mongodb 或 mongoose,同时添加数据和创建 id?我知道我可以做一个虚拟的,但我想要存储数据。

    附加信息
  • 如果用 mongodb 不可能做到这一点,有没有办法用 MySQL 做到这一点?
  • 做这种事情是否被认为是正确/错误的方法?
  • 最佳答案

    您基本上是在寻找 "pre" middleware通过在集合中创建新文档来触发“保存”事件。这将检查当前文档内容并从值中提取“字符串”,以便为 _id 创建“前缀”值。 .

    还有另一部分,当该特定“前缀”已经存在一个值以使其不同时,“前缀”需要添加数字计数器。 MongoDB 中有一个常用技术用于 "Generate an auto-incrementing sequence field" ,这基本上涉及保留一个“计数器”集合并在每次访问它时递增该值。

    作为一个完整且独立的演示,您可以按如下方式组合这些技术:

    var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

    mongoose.connect('mongodb://localhost/warehouse');

    var counterSchema = new Schema({
    "type": { "type": String, "required": true },
    "prefix": { "type": String, "required": true },
    "counter": Number
    });

    counterSchema.index({ "type": 1, "prefix": 1 },{ "unique": true });

    counterSchema.virtual('nextId').get(function() {
    return this.prefix + this.counter;
    });

    var productSchema = new Schema({
    "_id": "String",
    "category": {
    "object": { "type": String, "required": true },
    "group": { "type": String, "required": true },
    "name": { "type": String, "required": true }
    }
    },{ "_id": false });

    productSchema.pre('save', function(next) {
    var self = this;

    if ( !self.hasOwnProperty("_id") ) {

    var prefix = self.category.object.substr(0,1).toUpperCase()
    + self.category.group.substr(0,1).toUpperCase()
    + self.category.name.split(" ").map(function(word) {
    return word.substr(0,1).toUpperCase();
    }).join("");

    mongoose.model('Counter').findOneAndUpdate(
    { "type": "product", "prefix": prefix },
    { "$inc": { "counter": 1 } },
    { "new": true, "upsert": true },
    function(err,counter) {
    self._id = counter.nextId;
    next(err);
    }
    );
    } else {
    next(); // Just skip when _id is already there
    }
    });

    var Product = mongoose.model('Product',productSchema),
    Counter = mongoose.model('Counter', counterSchema);

    async.series(
    [
    // Clean data
    function(callback) {
    async.each([Product,Counter],function(model,callback) {
    model.remove({},callback);
    },callback);
    },
    function(callback) {
    async.each(
    [
    {
    "category": {
    "object": "ring",
    "group": "movies",
    "name": "lord of the rings"
    }
    },
    {
    "category": {
    "object": "ring",
    "group": "movies",
    "name": "four weddings and a funeral"
    }
    },
    {
    "category": {
    "object": "ring",
    "group": "movies",
    "name": "lord of the rings"
    }
    }
    ],
    function(data,callback) {
    Product.create(data,callback)
    },
    callback
    )
    },
    function(callback) {
    Product.find().exec(function(err,products) {
    console.log(products);
    callback(err);
    });
    },
    function(callback) {
    Counter.find().exec(function(err,counters) {
    console.log(counters);
    callback(err);
    });
    }
    ],
    function(err) {
    if (err) throw err;
    mongoose.disconnect();
    }
    )

    这为您提供如下输出:

    [ { category: { name: 'lord of the rings', group: 'movies', object: 'ring' },
    __v: 0,
    _id: 'RMLOTR1' },
    { category:
    { name: 'four weddings and a funeral',
    group: 'movies',
    object: 'ring' },
    __v: 0,
    _id: 'RMFWAAF1' },
    { category: { name: 'lord of the rings', group: 'movies', object: 'ring' },
    __v: 0,
    _id: 'RMLOTR2' } ]
    [ { __v: 0,
    counter: 2,
    type: 'product',
    prefix: 'RMLOTR',
    _id: 57104cdaa774fcc73c1df0e8 },
    { __v: 0,
    counter: 1,
    type: 'product',
    prefix: 'RMFWAAF',
    _id: 57104cdaa774fcc73c1df0e9 } ]

    先来了解 Counter模式和模型,您基本上是在定义一些东西,您将在其中查找“唯一”键,并在匹配时附加一个数字字段以“递增”。为方便起见,这只有两个字段组成唯一组合和定义的复合索引。这也可能只是一个化合物 _id如果想要的话。

    另一个方便的是 virtual nextId的方法,它只是将“前缀”和“计数器”值串联起来。由于您的 Counter 在此处包含诸如“类型”之类的内容也是此处的最佳实践模型可用于服务“计数器”以用于多个收集源。所以这里我们使用 "product"每当在 Product 的上下文中访问时模型以将其与其他模型区分开来,您可能还会保留类似的序列计数器。只是一个值得遵循的设计点。

    为实际 Product模型本身,我们要附加“预保存”中间件 Hook 以填充 _id内容。因此,在确定“前缀”的字符部分后,操作然后开始并在 Counter 中查找该“前缀”与“产品”类型数据的组合。模型集合。

    .findOneAndUpdate() 的功能是在“计数器”集合中查找与条件匹配的文档,然后在已经找到文档的地方“增加”当前 counter使用 $inc 的值更新运算符。如果未找到该文档,则 "upsert" option 意味着将创建一个新文档,无论如何,新文档中也会发生相同的“增量”。
    "new"这里的选项意味着我们希望返回“修改过的”文档(新的或已更改的),而不是文档在 $inc 之前的样子。被应用。结果是“计数器”值将 总是 每次访问增加。

    一旦完成,文档 Counter为匹配的键增加或创建,然后您现在可以使用一些东西分配给 _idProduct模型。如前所述,您可以使用 virtual在这里为了方便获取带有附加计数器值的前缀。

    因此,只要您的文档始终由 .create() 创建方法来自模型或使用 new Product()然后是 .save()方法,则始终执行代码中附加到“模型”的方法。

    请注意,由于您希望在 _id 中使用它,然后作为主键,这是“不可变的”并且不能改变。因此,即使引用的字段中的内容后来被更改, _id 中的值也是如此。无法更改,因此为什么这里的代码在 _id 时不尝试值已经设置。

    关于javascript - 使用其他字段的数据创建 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36629147/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com