110

文字列を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
4

18 に答える 18

195

マングースの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にキャストされたときに変更されるために機能します。

于 2015-03-24T11:08:58.997 に答える
95

正規表現を使用して、次のことをテストできます。

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    
}
于 2012-12-13T01:00:14.560 に答える
67

✅ビルドインソリューションisValidObjectId()>マングース5.7.12

Mongooseを使用している場合は、mongoose組み込みの isValidObjectIdを使用して、文字列が12バイトであるか24文字の16進文字であるかをテストできます。

mongoose.isValidObjectId(string); /* will return true/false */

注意してください!

isValidObjectId()マングースが無効なオブジェクトIDエラーをスローするのを避けるために、予想されるobjectIDをテストするために最も一般的に使用されます。

if (mongoose.isValidObjectId("some 12 byte string")) {
     return collection.findOne({ _id: "some 12 byte string" })
     // returns null if no record found.
}

期待されるobjectIDが有効かどうかを条件付きでテストしない場合は、エラーをキャッチする必要があります。

try {
  return collection.findOne({ _id: "abc" }) 
  //this will throw error
} catch(error) {
  console.log('invalid _id error', error)
}

findOne({ _id: null })およびfindOne({ _id: undefined })は完全に有効なクエリであり(エラーをスローしません)、trueisValidObjectId(undefined)isValidObjectId(null)返します。

注2を実行してください!

123456789012はbson文字列のようには見えないかもしれませんが、次のクエリはエラーをスローしないため、完全に有効なObjectIDです。(レコードが見つからない場合はnullを返します)。

findOne({ _id: ObjectId('123456789012')}) // ✅ valid query

313233343536373839303132は、24文字の文字列( 123456789012の16進値)のように見える場合がありますが、次のクエリはエラーをスローしないため、有効なObjectIdでもあります。(レコードが見つからない場合はnullを返します)

findOne({ _id: ObjectId('313233343536373839303132')}) // ✅ valid query

以下は無効です(上記の例より1文字少ない文字)

findOne({ _id: ObjectId('12345678901')}) // ❌ not 12 byte string
findOne({ _id: ObjectId('31323334353637383930313')}) // ❌ not 24 char hex

ObjectIdの形式

ObjectIdは小さく、おそらく一意であり、生成が速く、順序付けられています。ObjectId値の長さは12バイトで、次のもので構成されます。

  • Unixエポックからの秒数で測定されたObjectIdの作成を表す4バイトのタイムスタンプ値
  • プロセスごとに1回生成される5バイトのランダム値。このランダムな値は、マシンとプロセスに固有です。
  • ランダムな値に初期化された3バイトのインクリメントカウンター

上記のランダムな値のため、ObjectIdを計算できません。12バイトの文字列または24文字の16進文字列としてのみ表示されます。

于 2020-08-31T08:13:08.327 に答える
12

私は過去にこれを行うためにネイティブノードmongodbドライバーを使用しました。isValidメソッドは、値が有効なBSONObjectIdであることを確認します。こちらのドキュメントを参照してください。

var ObjectID = require('mongodb').ObjectID;
console.log( ObjectID.isValid(12345) );
于 2014-07-15T16:23:55.490 に答える
5

文字列に12文字が含まれている場合、mongoose.Types.ObjectId.isValid(string)は常に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
于 2018-08-30T15:29:50.560 に答える
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;
}
于 2016-03-30T19:21:26.070 に答える
2

私が見つけた唯一の方法は、チェックしたい値で新しい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
于 2018-04-18T13:03:17.853 に答える
2

文字列が有効なMongoObjectIdであるかどうかを確認する最も簡単な方法は、mongodbモジュールを使用することです。

const ObjectID = require('mongodb').ObjectID;

if(ObjectID.isValid(777777777777777)){
   console.log("Valid ObjectID")
}
于 2020-07-17T17:39:22.397 に答える
1

最も簡単な方法は、基本的にObjectIdメソッドをtryandcatchサービスでラップすることです。次に、メソッドを直接使用する代わりに、このサービスを使用してオブジェクト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を取得することもできます。

于 2019-06-23T08:09:10.340 に答える
1

以下は、ObjectIdメソッドでチェックし、同じ値を返すisValidかどうかをチェックする関数です。一人で十分ではないnew ObjectId(id)理由は、選ばれた答えの中でアンディ・マクラウドによって非常によく説明されています。isValid

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;
}
于 2020-01-30T18:10:05.443 に答える
1

@ross-uの答えは素晴らしいです。

インラインで完全な検証を行うためのメソッドを連鎖させました。

documentId = id && isValid(id) && new ObjectId(id) == id ? id : null

二重等号に注意してください。これはnew ObjectId()文字列を返さないため非常に重要であり、厳密な比較では通常の文字列(ロジックに含まれている)と比較するとfalseが返されます。

メソッドはmongoose、requireによって公開されたオブジェクトから分解されています。

const {
  Types: {
    ObjectId: { isValid },
    ObjectId
  }
} = require("mongoose");
于 2020-02-28T09:23:35.460 に答える
1

このアプローチは誰かを助けるかもしれません。nodejsmongodbドライバーで動作します

if (ObjectId.isValid(stringId) && (ObjectId(stringId).toString() === stringId)){
  // your operation
}
于 2021-07-02T13:14:28.163 に答える
0

16進文字列がある場合は、次を使用できます。

ObjectId.isValid(ObjectId.createFromHexString(hexId));
于 2016-04-21T22:24:00.143 に答える
0

@Andy MacleodがobjectId値を独自の文字列と比較することを提案したものが、次の場所でExpress.jsサーバーをクラッシュさせていたため、有効なソリューションを取得するのにしばらく時間がかかりました。

var view_task_id_temp=new mongodb.ObjectID("invalid_id_string"); //this crashed

これを解決するために、単純なtrycatchを使用しました。

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
}
于 2016-09-15T18:14:51.663 に答える
0

マングースの場合、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');
}
于 2017-10-23T05:43:02.347 に答える
0

Andy Macleodの受け入れられた答えに加えて、文字列とObjectIdの両方をチェックするために使用できるヘルパー関数を作成しました。

含意:

var ObjectId = require("mongoose").Types.ObjectId;


function isValidObjectId(value) {
  // If value is an ObjectId cast it to a string to allow
  // passing string or ObjectId as an argument.
  var valueString = typeof value === "string" ? value : String(value); 
  
  // Cast the string to ObjectId
  var idInstance = new ObjectId(valueString); 

  return String(idInstance) === valueString;
}

説明:

受け入れられた答えの中で、アンディ・マクラウドは次のように述べています。

私のために働いているのは、文字列をobjectIdにキャストしてから、元の文字列がobjectIdの文字列値と一致することを確認することです。


無効なObjectId文字列を使用

ObjectIdに無効な文字列(のような"microsoft")をキャストすると、完全に異なる値が得られます。

        "microsoft"
            ↓
String( new ObjectId("microsoft")  );
            ↓
"6d6963726f736f6674313233"
            ↓
"microsoft" === "6d6963726f736f6674313233" // false

有効なObjectId文字列を使用

()のような有効な文字列"6d6963726f736f6674313233"をObjectIdにキャストすると、同じ値が得られます。

"6d6963726f736f6674313233"
            ↓
String( new ObjectId("6d6963726f736f6674313233") )
            ↓
"6d6963726f736f6674313233"     
            ↓
"6d6963726f736f6674313233" === "6d6963726f736f6674313233"  // true
于 2020-02-27T22:57:02.737 に答える
0

https://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html#objectid-isvalid

MongoDBドキュメントから:

コンストラクターのドキュメント:

ObjectID()
Constructor
Create a new ObjectID instance

class ObjectID()
    Arguments:  
        id (string) – Can be a 24 byte hex string, 12 byte binary string or a Number.
    Returns:    
        object instance of ObjectID.

ObjectId.isValid()ドキュメント:

Checks if a value is a valid bson ObjectId

ObjectID.isValid()
    Returns:    boolean return true if the value is a valid bson ObjectId, return false otherwise.

したがって、isValid(...)引数が有効なBSON ObjectIdオブジェクトであり、コンストラクターObjectId(...)が有効なBSON ObjectIdオブジェクト引数のみを受け入れる場合はtrueを返します(基本的に、isValid(...)コンストラクターによって例外がスローされる場合はfalseを返します)。

これを知っています。最初に引数が有効かどうかを確認してから、その値を使用してObjectIdを作成し、ObjectIdHEX文字列を比較できます。

const objectId = 'str_object_id';
const isValid = ObjectId.isValid(objectId) && new ObjectId(objectId).toHexString() == objectId;

渡されobjectIdたものが有効なObjectIdHEX文字列でない場合(コンストラクターによって変換されていない場合)、このメソッドはfalseを返します。

于 2022-01-21T12:40:15.393 に答える
-2

警告:isValidは、有効な16進数で始まる任意の12/24の長さの文字列に対してtrueを返します。現在、これはより良いチェックだと思います:

((thing.length === 24 || thing.length === 12) && isNaN(parseInt(thing,16)) !== true)

于 2014-12-23T23:09:30.267 に答える