【问题标题】:Creating a Mongoose BulkWrite Plugin创建 Mongoose BulkWrite 插件
【发布时间】:2021-05-28 16:53:24
【问题描述】:

我正在为 bulkWrite 操作而苦苦挣扎。我正在尝试创建大量操作来更新我的集合中的文档。对于创建的每个文档,都会使用一个插件。

const documents = [];
const count = 1000;
for (let i = 0; i < count; i++) {
    documents.push(
        {
            updateOne:
            {
                filter: { itemId: i },
                update: { $set: { name: i } },
                upsert: true
            }
        }
    );
}
await MyModel.bulkWrite(documents);

每个文档都需要在文档创建或更新时具有更新日期。为此,我使用了一个插件。

const plugin = function updateAtPlugin(schema: any, options: any) {
    schema.add({ updatedAt: Date });
    schema.post('updateOne', function (next: any) {
        this.updatedAt = new Date;
        next();
    });
    if (options && options.index) {
        schema.path('updatedAt').index(options.index);
    }
};
export default plugin;

然后在创建模型之前使用此插件。

import { Schema, model } from 'mongoose';
import updatedAtPlugin from './update-plugin';
const MySchema: Schema = new Schema({
    itemId: {
        type: String,
        required: true,
        index: true
    },
    attributes: Object
});
MySchema.plugin(updatedAtPlugin);

const MyModel: any = model('my-name', MySchema);
export { MyModel };

除了 bulkWrite 函数,我还尝试将 initializeUnorderedBulkOp 与 find.upsert().updateOne() 结合使用。

在这两种情况下插件都不起作用。

非常感谢您的帮助。

提前致谢

------- 编辑 ------

我想详细说明我的用例。目标是为所有新的和更新的文档设置一个标志为真,并利用猫鼬插件来做到这一点。

const plugin = function updated(schema: any, options: any) {
    schema.post('updateOne', function (next: any) {
        this.flag = true
        next();
    });
    if (options && options.index) {
        schema.path('flag').index(options.index);
    }
};
export default plugin;
import { Schema, model } from 'mongoose';
import updated from './updated-plugin';
const MySchema: Schema = new Schema({
    itemId: {
        type: String,
        required: true,
        index: true
    },
    attributes: Object,
    flag: {
       type: Boolean, 
       default: true
    }
});
MySchema.plugin(updated);

const MyModel: any = model('my-name', MySchema);
export { MyModel };

原因是bulkWrite 没有发回upserted 文档。它只返回修改后的计数。我想对结果执行一个查询 MySchema.find({flag: true}) 循环,做一些魔术,然后为每个处理的项目 set the flag to false

除了插件之外,我还尝试了setDefaultsOnInsertsetOnInsert。可惜没有成功。

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    您不需要自定义插件,猫鼬已经内置了。

    { timestamps: true } 作为第二个参数添加到您的架构中会自动将createdAtupdatedAt 添加到您的所有文档中。

    const MySchema: Schema = new Schema({
        itemId: {
            type: String,
            required: true,
            index: true
        },
        attributes: Object
    }, { timestamps: true });
    

    【讨论】:

    • 感谢您的回答。 Unfortionaltly这不是我的解决方案。通过将时间戳设置为 true,我在 bulkWrite 中的所有文档都会更新,我想将更新的文档与未更新的文档分开。所以也许我应该改变我的例子。我想创建一个插件,在插入或更新文档时将更新标志设置为 true。这可能吗?
    • 我仍然不清楚您要达到的目标。无论您的文档是否更新,设置 timestampstrue 都应添加 updatedAt 字段。 “我想将更新的文档与未更新的文档分开。”你能详细说明一下吗?
    • 我已经更新了我的帖子,希望这样更清楚。干杯
    • 还有一件事。如果您在列表中添加了 1000 个项目并且 timestamps = true ,则修改的计数始终为 1000,因为所有项目都已更新,即使唯一更新的是实际时间戳本身。对我来说这是个问题,因为我只想知道 1000 个更新中的哪些项目。
    • 我想我现在明白这个问题了。这是 mongoose 中的一个已知问题(?),目前无法完成,因为 mongoose 不知道文档在数据库中的样子,因此每当您尝试更新文档时它总是发送updatedAt , 是否有变化。有关更多信息,请参阅此 GitHub 问题:github.com/Automattic/mongoose/issues/6861
    猜你喜欢
    • 2021-07-06
    • 1970-01-01
    • 2021-12-23
    • 2019-12-20
    • 2022-11-18
    • 2016-05-15
    • 2020-01-26
    • 2020-08-10
    • 2019-01-31
    相关资源
    最近更新 更多