node.js - 查找 ObjectId _id 但 Schema 已将 _id 定义为 String

标签 node.js mongodb mongoose mongodb-query mongoose-schema

之前我没有声明 _id在我的架构中,所以每个新提交自然都会生成 MongoDB ObjectId因为它是 _id 。然而,要求已经改变,现在_id声明为String如下。

var mongoose = require("mongoose");
var Schema = mongoose.Schema;

var MySchema = new Schema({
    _id: {
        type: String,
    },
    schoolID: {
        type: mongoose.Schema.Types.ObjectId, ref: 'School'
    },
    points: {
        type: Number
    },
});
MySchema.index({ schoolID : 1})

module.exports = mongoose.model('Submission', MySchema);

但是,现在我无法使用 _id 找到之前插入的文档。根本不。我试过了

var submissionId = "60654319a8062f684ac8fde4"
Submission.findOne({ _id: mongoose.mongo.ObjectId(submissionId ) })
Submission.findOne({ _id: mongoose.Types.ObjectId(submissionId ) })
Submission.findOne({ _id: mongoose.ObjectId(submissionId ) })

但它总是会返回 null 。所以当我使用var mongoose = require('mongoose').set('debug', true);时要检查,它将显示在下面;我上面的所有查询仍然可以使用 String 找到,而不是ObjectId

Mongoose: submission.findOne({ _id: '60654319a8062f684ac8fde4' }, { projection: {} })

最佳答案

问题 - _id: { type: String,}, Mongoose 会在对数据库进行查询之前转换该值,因此在您的情况下,它将始终是一个字符串。

选项-1

将旧的 objectId 转换为字符串,因为您计划使用字符串 _id,因此最好保持一致。

从 shell Robomongo 运行这些命令

这将为现有 ObjectId 记录添加带有字符串 _id 的记录。

db.collection.find({}).toArray() // loop all records
    .forEach(function (c) {
        if (typeof c._id !== 'string') { // check _id is not string
            c._id = c._id.str; db.collection.save(c); // create new record with _id as string value
        }
    });

删除带有ObjectId的记录

db.collection.remove({ _id: { $type: 'objectId' } })

选项-2

添加 Mongoose 自定义类型。

https://mongoosejs.com/docs/customschematypes.html

class StringOrObjectId extends mongoose.SchemaType {
  constructor(key, options) {
    super(key, options, 'StringOrObjectId');
  }

  convertToObjectId(v) {
    const checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");
    let _val;
    try {
      if (checkForHexRegExp.test(v)) {
        _val = mongoose.Types.ObjectId(v);
        return _val;
      }
    } catch (e) {
      console.log(e);
    }
  }

  convertToString(v) {
    let _val = v;
    try {
      if(_.isString(_val)) return _val;
      if(_.isNumber(_val)) return _.toString(_val);
    } catch (e) {
      console.log(e);
    }
  }

  cast(val) {
    const objectIdVal = this.convertToObjectId(val);
    if (objectIdVal) return objectIdVal;

    const stringVal = this.convertToString(val)
    if (stringVal) return stringVal;

    throw new Error('StringOrObjectId: ' + val +
        ' Nor string nor ObjectId');
  }
}

mongoose.Schema.Types.StringOrObjectId = StringOrObjectId;

var MySchema = new Schema({
    _id: {
        type: StringOrObjectId, // custom type here
    },
    schoolID: {
        type: mongoose.Schema.Types.ObjectId, ref: 'School'
    },
    points: {
        type: Number
    },
});

查询

Submission.findOne({ _id: submissionId }); // it will cast ObjectId or String or throw error

缺点

  • 如果您的 _id 类型字符串为 60516ae1ef682d2804a2fa72,则类似于有效的 ObjectId,它将转换为与记录不匹配的 ObjectId

注意 - 这是一个粗略的类 StringOrObjectId 添加适当的检查并正确测试。


选项-3

简单的方法 - 使用mongoose.Mixed https://mongoosejs.com/docs/schematypes.html#mixed

https://mongoosejs.com/docs/api.html#mongoose_Mongoose-Mixed

cont MySchema = new Schema({
    _id: {
        type: mongoose.Mixed,
    },
    schoolID: {
        type: mongoose.Schema.Types.ObjectId, ref: 'School'
    },
    points: {
        type: Number
    },
});

关于node.js - 查找 ObjectId _id 但 Schema 已将 _id 定义为 String,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66932544/

相关文章:

c# - 在不创建查询对象的情况下使用 C# Mongo 驱动程序进行查询?

mongodb - Mongoose 和部分选择/更新

javascript - Azure Functions 中通过整数 SQL 查询 DocumentDB 不起作用

mongodb - Mongo Multikeys 作为索引的替代品?

javascript - 将 100 万个对象发送到 Mongo DB,而不会耗尽内存

javascript - 如何使用 MongoDB/Mongoose.js 查询类似 OR/AND 的条件?

node.js - Jest 、 Mongoose 和异步/等待

javascript - Node 上的 gifencoder 抛出 TypeError

javascript - 无法通过 fetch 方法访问 HTMLCollection Item

node.js - 无法使用express js在node js中下载csv文件