Estoy haciendo búsquedas de MongoDB convirtiendo una cadena a BSON. ¿Hay alguna forma de determinar si la cadena que tengo es un ObjectID válido para Mongo antes de realizar la conversión?
Aquí está el coffeescript de mi función findByID actual. Funciona muy bien, pero me gustaría buscar por un atributo diferente si determino que la cadena no es una ID.
db.collection "pages", (err, collection) ->
collection.findOne
_id: new BSON.ObjectID(id)
, (err, item) ->
if item
res.send item
else
res.send 404
Respuestas:
Descubrí que el validador de ObjectId de mangosta funciona para validar objectIds válidos, pero encontré algunos casos en los que los identificadores no válidos se consideraron válidos. (por ejemplo: cualquier cadena de 12 caracteres)
var ObjectId = require('mongoose').Types.ObjectId; ObjectId.isValid('microsoft123'); //true ObjectId.isValid('timtomtamted'); //true ObjectId.isValid('551137c2f9e1fac808a5f572'); //true
Lo que me ha funcionado es lanzar una cadena a un objectId y luego verificar que la cadena original coincida con el valor de la cadena del objectId.
new ObjectId('timtamtomted'); //616273656e6365576f726b73 new ObjectId('537eed02ed345b2e039652d2') //537eed02ed345b2e039652d2
Esto funciona porque los identificadores válidos no cambian cuando se convierten en un ObjectId, pero una cadena que obtiene un falso válido cambiará cuando se convierte en un objectId.
fuente
function checkObjectIdValid(id){ if(ObjectID.isValid(id)){ if(new ObjectID(id) === id){ return true } else { return false } } else { return false } }
const ObjectId = require('mongoose').Types.ObjectId; function isObjectIdValid(id) { if (ObjectId.isValid(id)) { if (String(new ObjectId(id)) === id) { return true } else { return false } } else { return false } }
es6
eso:isObjectIdValid = id => ObjectId.isValid(id) ? String(new ObjectId(id) === id) ? true : false : false;
Puede usar una expresión regular para probar eso:
CoffeeScript
if id.match /^[0-9a-fA-F]{24}$/ # it's an ObjectID else # nope
JavaScript
if (id.match(/^[0-9a-fA-F]{24}$/)) { // it's an ObjectID } else { // nope }
fuente
lol456712bbfghLLsdfr
He utilizado el controlador mongodb de nodo nativo para hacer esto en el pasado. El método isValid comprueba que el valor sea un ObjectId BSON válido. Consulte la documentación aquí.
var ObjectID = require('mongodb').ObjectID; console.log( ObjectID.isValid(12345) );
fuente
ObjectId
, noObjectID
. :)Si está utilizando Mongoose, podemos probar si una cadena tiene 12 bytes o una cadena de 24 caracteres hexadecimales mediante el uso de isValidObjectId integrado de mangosta .
Esta es una solución mejorada proporcionada por una solución aceptada .
fuente
Aquí hay un código que he escrito basado en la respuesta de @ andy-macleod.
Puede tomar un int o string o ObjectId y devuelve un ObjectId válido si el valor pasado es válido o nulo si no es válido:
var ObjectId= require('mongoose').Types.ObjectId; function toObjectId(id) { var stringId = id.toString().toLowerCase(); if (!ObjectId.isValid(stringId)) { return null; } var result = new ObjectId(stringId); if (result.toString() != stringId) { return null; } return result; }
fuente
mongoose.Types.ObjectId.isValid (cadena) siempre devuelve Verdadero si la cadena contiene 12 letras
let firstUserID = '5b360fdea392d731829ded18'; let secondUserID = 'aaaaaaaaaaaa'; console.log(mongoose.Types.ObjectId.isValid(firstUserID)); // true console.log(mongoose.Types.ObjectId.isValid(secondUserID)); // true let checkForValidMongoDbID = new RegExp("^[0-9a-fA-F]{24}$"); console.log(checkForValidMongoDbID.test(firstUserID)); // true console.log(checkForValidMongoDbID.test(secondUserID)); // false
fuente
La única forma que encontré es crear un nuevo ObjectId con el valor que quiero verificar, si la entrada es igual a la salida, la identificación es válida:
function validate(id) { var valid = false; try { if(id == new mongoose.Types.ObjectId(""+id)) valid = true; } catch(e) { valid = false; } return valid; } > validate(null) false > validate(20) false > validate("abcdef") false > validate("5ad72b594c897c7c38b2bf71") true
fuente
La forma más fácil es básicamente envolver su método ObjectId en un servicio de prueba y captura. Entonces está usando este servicio para manejar los Id de Objecet, en lugar de usar el método directamente:
var ObjectId = REQUIRE OR IMPORT ... // service function oid(str) { try { return ObjectId(str); } catch(err) { return false; } } // usage if (oid(USER_INPUT)) { // continue } else { // throw error }
También puede enviar accesorios nulos o vacíos para obtener una nueva ID generada.
fuente
La forma más sencilla de comprobar si la cadena es un ObjectId de Mongo válido es mediante el módulo mongodb .
const ObjectID = require('mongodb').ObjectID; if(ObjectID.isValid(777777777777777)){ console.log("Valid ObjectID") }
fuente
A continuación se muestra una función que verifica con el
isValid
método ObjectId y sinew ObjectId(id)
devuelve el mismo valor o no .isValid
Andy Macleod describe muy bien la razón de no ser suficiente solo en la respuesta elegida.const ObjectId = require('mongoose').Types.ObjectId; /** * True if provided object ID valid * @param {string} id */ function isObjectIdValid(id){ return ObjectId.isValid(id) && new ObjectId(id) == id; }
fuente
Si tiene la cadena hexadecimal, puede usar esto:
ObjectId.isValid(ObjectId.createFromHexString(hexId));
fuente
Me tomó un tiempo obtener una solución válida, ya que la propuesta por @Andy Macleod de comparar el valor de objectId con su propia cadena estaba bloqueando el servidor Express.js en:
var view_task_id_temp=new mongodb.ObjectID("invalid_id_string"); //this crashed
Solo utilicé un simple intento de captura para resolver esto.
var mongodb = require('mongodb'); var id_error=false; try{ var x=new mongodb.ObjectID("57d9a8b310b45a383a74df93"); console.log("x="+JSON.stringify(x)); }catch(err){ console.log("error="+err); id_error=true; } if(id_error==false){ // Do stuff here }
fuente
Para mangosta, use la función isValid () para verificar si objectId es válido o no
Ejemplo:
var ObjectId = mongoose.Types.ObjectId; if(ObjectId.isValid(req.params.documentId)){ console.log('Object id is valid'); }else{ console.log('Invalid Object id'); }
fuente
En la respuesta de la solución, Andy Macleod dijo:
Una implementación de este enfoque sería una función que verifica si el valor pasado es válido
ObjectId
y funciona con los valoresstring
yObjectId
(objeto). Se vería así:var ObjectId = require("mongoose");.Types.ObjectId; function isValidObjectId(value) { // If value is an object (ObjectId) cast it to a string var valueString = typeof value === "string" ? value : String(value); // Cast the string to ObjectId var idInstance = new ObjectId(valueString); return String(idInstance) === valueString; }
fuente
La respuesta de @ ross-u es simplemente increíble.
He encadenado los métodos para hacer una validación completa en línea:
documentId = id && isValid(id) && new ObjectId(id) == id ? id : null
Tenga en cuenta el doble signo igual, que es MUY importante ya
new ObjectId()
que no devuelve una cadena y la comparación estricta devolverá falso en comparación con una cadena normal (que tenía en mi lógica).Los métodos se han desestructurado del
mongoose
objeto expuesto por el requisito:const { Types: { ObjectId: { isValid }, ObjectId } } = require("mongoose");
fuente
Advertencia: isValid devolverá verdadero para cadenas arbitrarias de 12/24 de longitud que comiencen con un dígito hexadecimal válido. Actualmente creo que esta es una mejor verificación:
fuente
true
para'funky string'
. Cualquier cadena que tenga la longitud correcta y comience con un dígito hexadecimal la satisfará.