文字列をBSONに変換してMongoDBルックアップを行っています。変換を行う前に、持っている文字列がMongoの有効なObjectIDであるかどうかを判断する方法はありますか?
以下は、現在のfindByID関数のコーヒースクリプトです。うまくいきますが、文字列がIDではないと判断した場合は、別の属性で検索したいと思います。
db.collection "pages", (err, collection) ->
collection.findOne
_id: new BSON.ObjectID(id)
, (err, item) ->
if item
res.send item
else
res.send 404
Mongoose ObjectIdバリデーターは有効なobjectIdを検証するために機能することがわかりましたが、無効なIDが有効と見なされるいくつかのケースを見つけました。 (例:12文字の文字列)
var ObjectId = require('mongoose').Types.ObjectId;
ObjectId.isValid('Microsoft123'); //true
ObjectId.isValid('timtomtamted'); //true
ObjectId.isValid('551137c2f9e1fac808a5f572'); //true
私のために働いているのは、文字列をobjectIdにキャストし、元の文字列がobjectIdの文字列値と一致することを確認することです。
new ObjectId('timtamtomted'); //616273656e6365576f726b73
new ObjectId('537eed02ed345b2e039652d2') //537eed02ed345b2e039652d2
これは、有効なIDはObjectIdにキャストされても変化しませんが、falseの有効な文字列はobjectIdにキャストされると変化するためです。
正規表現を使用して、それをテストできます。
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
}
過去にネイティブノードmongodbドライバーを使用してこれを実行しました。 isValidメソッドは、値が有効なBSON ObjectIdであることを確認します。 こちらのドキュメントをご覧ください
var ObjectID = require('mongodb').ObjectID;
console.log( ObjectID.isValid(12345) );
@ 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;
}
mongoose.Types.ObjectId.isValid(string)は、文字列に12文字が含まれている場合、常にTrueを返します
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
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');
}
ObjectId値と独自の文字列を比較する@Andy Macleodが提案したものが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
}
16進文字列がある場合、これを使用できます。
ObjectId.isValid(ObjectId.createFromHexString(hexId));
私が見つけた唯一の方法は、チェックしたい値で新しいObjectIdを作成することです。入力が出力と等しい場合、idは有効です:
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
最も簡単な方法は、基本的にObjectIdメソッドをtry and catchサービスでラップすることです。次に、メソッドを直接使用する代わりに、このサービスを使用してObjecet Idを処理します。
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
}
Nullまたは空の小道具を送信して、新しい生成されたIDを取得することもできます。