猫鼬复杂查询,用于更新和插入数据

时间:2018-10-01 06:20:15

标签: javascript node.js mongodb mongoose

我有这样的模型:

var MyModel = new mongoose.Schema({
 key: String,
 array_values : [{
    value: String,
    counter: { type: Number, default: 1}
}];

我需要插入一个键值对,以便:

  1. 如果没有key,则添加了一个新文档;
  2. 如果有key,则:
    • 如果value中有一个array_values,则counter字段的值会增加
    • 否则,如果没有这样的value,则只需将新对象{key, counter}添加到array_value

例如,有一个文档:

{
 key: "key",
 array_values: [{value: "value", counter: 1}]
}

插入{key: "key", value: "value"}时应为:

{
 key: "key",
 array_values: [{value: "value", counter: 2}]
}

在插入{key: "key_1", value: "value"}时,应添加一个文档:

{
 key: "key",
 array_values: [{value: "value", counter: 1}]
},
{
 key: "key_1",
 array_values: [{value: "value", counter: 1}]
}

插入{key: "key", value: "value_1"}时应为:

{
 key: "key",
 array_values: [
    {value: "value", counter: 1}, 
    {value: "value_1", counter: 1}]
}

是否可以使用一个查询来执行此操作?

在此之前,我使用了.findOne({key: 'findingKey'}),然后处理了结果,但是处理大量key-value的过程很慢

UPD:

这是我尝试做的事情:

我添加了一个静态函数:

MyModel.statics.addKeyValue = async function (key, value) {
    let item = await this.findOne({key: key}).exec();
    if (item) {
        const arr = item.array_values;
        let findItem = arr.find((arrItem) => {
            return arrItem.value === value;
        });

        if (findItem !== undefined) {
            findItem.count += 1;
        } else {
            item.array_values.push({value: value, counter: 1});
        }
        await item.save();
    } else {
        await this.create({
            key : key,
            array_values: [{value: value, counter: 1}]
        });
    }
};

但是要插入17万个值需要花费超过10个小时的时间

2 个答案:

答案 0 :(得分:0)

您可以尝试以下查询。它将从请求正文中找到文档并提供,并将根据猫鼬查询返回的结果进行更新或创建。

MyModel.findOne({key: req.body.key}, (err, result) => {
    if (!result) {
        result = new Model();
        result.key = req.body.key;
        result.array_values = [];
    }
    result.array_values.push(req.body.array_values);
    result.save();
})

希望这对您有所帮助。

答案 1 :(得分:0)

您尝试过findOneAndUpdate吗? https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/

也许这对你有用 例如:-

MyModel.findOneAndUpdate(
    { key: 'key3' }, 
    { $inc: { 'array_values.counter': 1 } }, 
    { upsert: true }
)

这并非在所有情况下都适用,在第一种和第二种情况下都适用。 让我知道它是否有效