猫鼬只更新所选字段或插入

时间:2019-04-24 18:58:56

标签: javascript mongodb mongoose mongodb-query

标题听起来像findOne$set一样,但我却无法以我想要的方式工作。

首先,我有一个Ticket模式

const Ticket = new Schema(Object.assign({
    ticketNumber: { type: String, required: true },
    year: { type: Schema.Types.Mixed, default: [] },  // object

}, BaseSchema), { timestamps: true });

然后我有一个将数据写入db的功能。

我在下面的代码中也有一个模拟数据

exports.writeToDB = async () => {
    const data = [
        {
            ticketNumber: 123456789,
            year: 2019,
            notes: 'hello there',
            more: 'there should be more fields here'
        },
        {
            ticketNumber: 987654321,
            year: 2020,
            notes: 'hello there again',
            more: 'there should be more fields here again'
        }
    ];

    data.forEach(d => {
        console.log(d, 'ddd');
        const { ticketNumber, year, ...contents } = d;
        const query = { ticketNumber };
        const update = {
            'year': { [year]: contents }
        };
        const options = { upsert: true };
        Ticket.updateOne(query, update, options, (err, doc) => {
            console.log(doc, 'docc');
        })
    })
};

在模式中,只有ticketNumberyear 开始时一切都很好,但是我想做的是,年份可能会有所不同,ticketNumber将保持不变。每次传递数据时,如果找到ticketNumber,则根据update year,如果找不到year,则改为insert

数据库中的示例

{
    ticketNumber: 123456789,
    year: {
        2019: {
            notes: 'hello there',
            more: 'there should be more fields here'
        }
    }
};

如果以同一年份2019传递数据,则它将更新notesmore字段以及其他字段,但是如果数据以不同年份传递,例如2020,那么db中的内容应该看起来像...

{
    ticketNumber: 123456789,
    year: [
        2019: {
            notes: 'hello there',
            more: 'there should be more fields here'
        },
        2020: {
            notes: 'hello there',
            more: 'there should be more fields here'
        },
    ]
};

我尝试将update变量配置为此类

const update = {
    $set: {'year': { [year]: contents }}
};


const update = {
    'year': $set{ [year]: contents }
};

但是它们两个都不起作用,第一个将覆盖整个对象(有点像预期的那样)。第二个人实际上什么也没做

关于我应该做什么的任何建议,或者我应该提供其他逻辑而不是使用类似$set的东西?

在此先感谢您的帮助和建议。

1 个答案:

答案 0 :(得分:1)

我检查了猫鼬api,并且Model.update方法在documentation中有此注释:

所有不是原子操作名称的顶级键都被视为设置操作:

示例

var query = { name: 'borne' };
Model.update(query, { name: 'jason bourne' }, options, callback);

// is sent as
Model.update(query, { $set: { name: 'jason bourne' }}, options, function(err, res));
// if overwrite option is false. If overwrite is true, sent without the $set wrapper.

因此,在猫鼬上使用$set时,您不必手动指定Model.update,只需执行以下操作:

const update = {
    [`year.${year}`]: contents
};