我的模特

const mongoose = require('mongoose');

const TelemetrySchema = new mongoose.Schema({
  MQTT: {
    Id: { type: String, trim: true, required: true },
  },
  Presets: [{
    Id: Number,
    Message: String,
  }],
});

module.exports = mongoose.model('Telemetry', TelemetrySchema);

我想做的是:

如果具有指定ID的对象已存在,则覆盖它.如果对象尚不存在,则使用指定ID创建一个新对象.

我收到了一个Preset个对象,以及模型中的预设应该是什么样子:

T=0:{Id: 1, Message: 'A'}->[{Id: 1, Message: 'A'}]

T=1:{Id: 2, Message: 'B'}->[{Id: 1, Message: 'A'}, {Id: 2, Message: 'B'}]

T=3:{Id: 1, Message: 'Z'}->[{Id: 1, Message: 'Z'}, {Id: 2, Message: 'B'}]

有没有可能只用一个findOneAndUpdate?我有个可行的办法但我不喜欢...

client.on('message', async (topic, payload) => {
  const s = payload.toString();
  const p = JSON.parse(s);
  const id = topic.split('/');

  const existingTelemetry = await Telemetry.findOne({
    'MQTT.Id': id[1],
    'Presets.Id': p.Id,
  });

  if (existingTelemetry) {
    // If an object with the same id exists, update the existing object
    await Telemetry.findOneAndUpdate(
      {
        'MQTT.Id': id[1],
        'Presets.Id': p.Id,
      },
      {
        $set: {
          'Presets.$': p,
        },
      },
      {
        new: true,
        omitUndefined: true,
      },
    );
  } else {
    // If no object with the same id exists, add the new object
    await Telemetry.findOneAndUpdate(
      {
        'MQTT.Id': id[1],
      },
      {
        $addToSet: {
          Presets: p,
        },
      },
      {
        upsert: true,
        new: true,
        omitUndefined: true,
      },
    );
  }
});

推荐答案

这就是我在类似场景中执行更新的方式,我将解释为什么我以这种方式而不是聚合管道来执行更新.

首先,实现这一点的聚合管道当然是可行的.然而,当你在3/6/12/x个月后更新代码时,你将需要花费一些脑力来阅读流水线并弄清楚你到底写了什么.使用聚合管道,它们可能在很长一段时间后很难阅读,并且如果您的模式发生变化,可能很难进行调整,至少我是这样认为的.

其次,当您查看下面的代码时,您和您的团队很容易就能清楚地看到发生了什么.

最后,这也是与您的代码的唯一不同之处,在下面的代码中,您只需要在some的时间中命中数据库once,因为if(!doc)可能只是很少的true.而在上面的代码中,您将always命中数据库twice(1xfindOne+1xfindOneAndUpdate).

现在,根据这些更新第一次匹配的频率,可能是60/70/80%,所以if(!doc)中的第二个findOneAndUpdate永远不会被解雇,或者只有10/20/30%的时间被解雇.这可能是一个可以接受的容忍.

// Assign the return value to 'doc'
const doc = await Telemetry.findOneAndUpdate(
    {
       'MQTT.Id': id[1],
       'Presets.Id': p.Id,
    },
    {
       $set: {
          'Presets.$': p,
       },
    },
    {
       new: true,
       omitUndefined: true,
    },
);
if(!doc){ //< There was no match and no update so $addToSet
   await Telemetry.findOneAndUpdate(
      {
         'MQTT.Id': id[1],
      },
      {
         $addToSet: {
            Presets: p,
         },
      },
      {
         upsert: true,
         new: true,
         omitUndefined: true,
      },
   );
}

Javascript相关问答推荐

Python类实现的JavaScript吊坠是什么样子的?

想要检测字符串中的所有单词

使用json文件字符串来enum显示类型字符串无法按照计算的enum成员值的要求分配给类型号

zoom svg以适应圆

如何从JSON数组添加Google Maps标记—或者如何为数组添加参数到标记构造器

在Angular中将样式应用于innerHTML

React Code不在装载上渲染数据,但在渲染上工作

如何禁用附加图标点击的v—自动完成事件

如何使覆盖div与可水平滚动的父div相关?

有没有可能使滑动img动画以更快的速度连续?

如何根据当前打开的BottomTab Screeb动态加载React组件?

使用ThreeJ渲染的形状具有抖动/模糊的边缘

在WordPress中使用带有WPCode的Java代码片段时出现意外令牌错误

当代码另有说明时,随机放置的圆圈有时会从画布上消失

使用RxJS from Event和@ViewChild vs KeyUp事件和RxJS主题更改输入字段值

如何在AG-Grid文本字段中创建占位符

用于测试其方法和构造函数的导出/导入类

Jexl to LowerCase()和Replace()

Reaction useState和useLoaderData的组合使用引发无限循环错误

P5JS-绘制不重叠的圆