验证 MongoDB ObjectId

15

有没有一种方法可以在不实际访问 MongoDB 数据库的情况下验证 MongoDB 的 ObjectId?例如,字符串值"5c0a7922c9d89830f4911426"应该返回"true"


1
你能解释一下你是否想知道 ObjectId 是否实际存在,或者如果它只是一个潜在的有效 ObjectId 字符串,那么这对你是否可以接受?因为在后一种情况下,这里的答案可能会对你有所帮助:https://dev59.com/KWct5IYBdhLWcg3wk-Vq - Virginia
7个回答

34
你可以在mongoose中使用.isValid()方法来验证ObjectId是否有效:
var mongoose = require('mongoose');
var isValid = mongoose.Types.ObjectId.isValid('5c0a7922c9d89830f4911426'); //true

如果我传递一个长度为12的字符串会发生什么?var isValid = mongoose.Types.ObjectId.isValid('lkjyuhgfdres') - Sudarshana Dayananda
@SudarshanaDayananda 当然无效,因为它包含非十六进制字符。 - mickl
但是在问题中并没有提到十六进制/非十六进制。它是关于验证任何字符串是否为有效的MongoDB id。 - Sudarshana Dayananda
@SudarshanaDayananda 一个有效的MongoDB ObjectID只包含十六进制字符。因此,像“lkjyuhgfdres”这样的字符串显然不是有效的ObjectID。还要注意,这仅验证id是否有效,而不是它是否存在于数据库中。 - mhombach
2
任何12个字符的字符串都可以通过此。 - Tushar Shahi
@TusharShahi 是的,你是正确的;我建议使用这个小型的npm包 https://www.npmjs.com/package/joi-objectid - Abd

7
请注意,在几乎所有情况下,您只需处理catch而不必担心ObjectID的有效性,因为如果提供了无效的ObjectId,mongoose会抛出异常throw
Model.findOne({ _id: 'abcd' }).exec().catch(error => console.error('error', error));

除此之外,您可以使用mongoose.Types.ObjectId.isValid或正则表达式:/^[a-fA-F0-9]{24}$/


2

@mickl的答案对于长度为12的字符串将会失败。

你应该使用mongodb中的ObjectId构造函数将任何给定的字符串转换为MongoDB ObjectId,然后将其转换为字符串并再次与原始字符串进行比较。它应该是相同的。

  import { ObjectId } from 'mongodb'

  function isValidId(id) {

     return new ObjectId(id).toString() === id;
  }

  isValidId('5c0a7922c9d89830f4911426')// true
  isValidId('lkjyuhgfdres')// false

2
这对我不起作用,它会导致mongodb客户端崩溃,并显示相同的错误信息:“传递的参数必须是12个字节的单个字符串或24个十六进制字符的字符串”。 - Sam Sverko
1
把它放在try-catch块中?try返回true,catch返回false... - TJBlackman

0
let mongoose = require('mongoose'); 
let ObjectId = mongoose.Types.ObjectId; 
let recId1 = "621f1d71aec9313aa2b9074c"; 
let isValid1 = ObjectId.isValid(recId1); //true 
console.log("isValid1 = ", isValid1); //true 
let recId2 = "621f1d71aec9313aa2b9074cd"; 
let isValid2 = ObjectId.isValid(recId2); //false
console.log("isValid2 = ", isValid2); //false

1
目前你的回答不够清晰。请编辑并添加更多细节,以帮助其他人理解它如何回答所提出的问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

0

如果您使用Joi进行验证,您可以直接在您的Joi模式中包含验证,使用joi-objectid

安装joi-objectid:$ npm i joi-objectid

定义全局使用的函数(已导入Joi):

Joi.objectId = require('joi-objectid')(Joi)

在你的 Joi schema 中使用它:

function validateUser(user) {
    const schema = {
        userId: Joi.objectId().required(),
        name: Joi.string().required()
    };
    return Joi.validate(user, schema);
}

0

提供的API(Mongoose.prototype.isValidObjectId()和较新版本)对于随机字符串如Manajemenfs2返回true。

使用mongoose,我最终是这样做的:

import mongoose from 'mongoose';


const isValidMongoId = (id: string) => {  
  try {
    const objectID = new mongoose.Types.ObjectId(id);
    const objectIDString = objectID.toString();
    return objectIDString === id;
  } catch (e){
    return false;
  } 
};

方法的定义清楚地显示:


Mongoose.prototype.isValidObjectId = function(v) {
  if (v == null) {
    return true;
  }

  //Other code

  if (v.toString instanceof Function) {
    v = v.toString();
  }

  if (typeof v === 'string' && v.length === 12) {
    return true;
  }

  //Other code

  return false;
};

对于一般的原始字符串和字符串对象,任何长度为12的字符串都可以通过。


0

您可以在mongoose中使用内置函数

import { isValidObjectId } from "mongoose";

const isIDValid = isValidObjectId(id);

if (!isIDValid) throw { message: `Invalid ID provided` };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接