NodeJS MongoDB使用函数更新每个文档中字段

cygmwpex  于 2022-11-03  发布在  Node.js
关注(0)|答案(1)|浏览(223)

我需要更新所有现有的文档并加密敏感信息。我在代码中编写了一个脚本,如下所示,对每个文档中的“name”字段进行加密:

const update = await User.updateMany(
    {},
    {
      $set: {
        name: {
          $function: {
            body: function (name) {
              return encrypt(name);
            },
            args: ['$name'],
            lang: 'js'
          }
        }
      }
    }
  );

但是,我收到此错误:

server/node_modules/mongoose/lib/query.js:4777
  const castError = new CastError();
                    ^

CastError: Cast to string failed for value "{
  '$function': { body: [Function: body], args: [ '$name' ], lang: 'js' }
}" (type Object) at path "name"
    at model.Query.exec (/node_modules/mongoose/lib/query.js:4777:21)
    at model.Query.Query.then (/node_modules/mongoose/lib/query.js:4876:15)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  messageFormat: undefined,
  stringValue: '"{\n' +
    "  '$function': { body: [Function: body], args: [ '$name' ], lang: 'js' }\n" +
    '}"',
  kind: 'string',
  value: {
    '$function': { body: [Function: body], args: [ '$name' ], lang: 'js' }
  },
  path: 'name',
  reason: null,
  valueType: 'Object'
}

有人知道这是什么意思吗?我已经纠结了很久了谢谢

6l7fqoea

6l7fqoea1#

所以你实际上有多个问题与此代码,我将开始与错误您张贴。这是一个mongoose铸造错误。
您尝试使用aggregation $function函数作为正常更新的一部分,这是不允许的-mongoose又尝试将“name”值转换为字符串,因为这是它期望从模式定义中获得的。这是您得到的错误。
因此,要解决问题#1,您需要使用aggregation pipeline update syntax,它将允许使用$function,并停止使用mongoose,它的“模式”保护对于高级语法使用非常不利。
注解中提到的第二个问题是,由于Mongodb解析和执行代码的方式,它不像普通的“编译器”那样将函数调用转换为动态代码。
相反,它将这个“对象”发送到内部引擎,并在那里尝试执行它,因此在Mongo的内部评分中没有这样的函数。
为了克服这个问题,你需要先在mongo中存储你的自定义函数,这实际上很容易,如here所述:

db.system.js.insertOne(
   {
     _id: "encrypt",
     value : function(x) { return x; }
   }
);

现在,从#1的变化,你的代码应该工作。

相关问题