Могу ли я определить, является ли строка идентификатором объекта MongoDB?
Я делаю поиск MongoDB, преобразовывая строку в BSON. Есть ли способ определить, имеет ли строка, которая у меня есть, действительный ObjectID для Mongo перед выполнением преобразования?
Вот кофейник для моей текущей функции findByID. Он отлично работает, но я хотел бы искать другой атрибут, если я определяю, что строка не является идентификатором.
db.collection "pages", (err, collection) ->
collection.findOne
_id: new BSON.ObjectID(id)
, (err, item) ->
if item
res.send item
else
res.send 404
Ответы
Ответ 1
Я обнаружил, что проверщик валидации Mongoose ObjectId работает для проверки правильных объектов, но я обнаружил несколько случаев, когда неверные идентификаторы считались действительными. (например: любая строка длиной 12 символов)
var ObjectId = require('mongoose').Types.ObjectId;
ObjectId.isValid('microsoft123'); //true
ObjectId.isValid('timtomtamted'); //true
ObjectId.isValid('551137c2f9e1fac808a5f572'); //true
То, что работает для меня, - это литье строки в objectId, а затем проверка того, что исходная строка соответствует строковому значению объекта.
new ObjectId('timtamtomted'); //616273656e6365576f726b73
new ObjectId('537eed02ed345b2e039652d2') //537eed02ed345b2e039652d2
Эта работа, потому что действительные идентификаторы не изменяются при передаче в ObjectId, но строка, которая получает ложное значение, будет изменяться при нажатии на объект.
Ответ 2
Для этого можно использовать регулярное выражение:
CoffeeScript
if id.match /^[0-9a-fA-F]{24}$/
# it an ObjectID
else
# nope
JavaScript
if (id.match(/^[0-9a-fA-F]{24}$/)) {
// it an ObjectID
} else {
// nope
}
Ответ 3
Я использовал собственный драйвер node mongodb для этого в прошлом. Метод isValid проверяет, является ли значение действительным объектом BSON ObjectId. См. документацию здесь.
var ObjectID = require('mongodb').ObjectID;
console.log( ObjectID.isValid(12345) );
Ответ 4
Вот какой код я написал на основе ответа @andy-macleod.
Он может принимать int или string или ObjectId и возвращает действительный ObjectId, если переданное значение является допустимым или null, если оно недействительно:
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;
}
Ответ 5
Если у вас есть шестнадцатеричная строка, вы можете использовать это:
ObjectId.isValid(ObjectId.createFromHexString(hexId));
Ответ 6
Мне потребовалось некоторое время, чтобы получить правильное решение, поскольку тот, который предложил @Andy Macleod для сравнения значения objectId со своей собственной строкой, разбивал сервер Express.js на:
var view_task_id_temp=new mongodb.ObjectID("invalid_id_string"); //this crashed
Я просто использовал простой try catch, чтобы решить эту проблему.
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
}
Ответ 7
Для mongoose используйте функцию isValid(), чтобы проверить, действителен ли objectId или нет.
Пример:
var ObjectId = mongoose.Types.ObjectId;
if(ObjectId.isValid(req.params.documentId)){
console.log('Object id is valid');
}else{
console.log('Invalid Object id');
}
Ответ 8
Единственный способ, который я нашел, - это создать новый ObjectId со значением, которое я хочу проверить. Если вход равен выводу, идентификатор действителен:
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
Ответ 9
mongoose.Types.ObjectId.isValid(string) всегда возвращает True, если строка содержит 12 букв
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
Ответ 10
Самый простой способ - это обернуть ваш метод ObjectId в службу try and catch. Затем вы используете этот сервис для обработки идентификаторов Objecet, вместо того, чтобы использовать метод напрямую:
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
}
Вы также можете отправить пустой или пустой реквизит, чтобы получить новый сгенерированный идентификатор.
Ответ 11
Предупреждение: isValid вернет true для произвольных строк длины 12/24, начиная с действительной шестнадцатеричной цифры.
В настоящее время я думаю, что это лучше проверить:
((thing.length === 24 || thing.length === 12) && isNaN(parseInt(thing,16)) !== true)