문자열이 MongoDB ObjectID인지 확인할 수 있습니까?


81

문자열을 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

지금은 try catch 블록을 사용하면됩니다. 이것이 권장 솔루션입니까?

답변:


145

몽구스 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 valid를 가져 오는 문자열은 objectId로 캐스트 될 때 변경되기 때문에 작동합니다.


이론적으로이 두 가지 방법을 추가하여 아주 좋은 ObjectID 유효성 검사기를 생성 할 수 있습니다.
안토니

2
그래서, 이런거? function checkObjectIdValid(id){ if(ObjectID.isValid(id)){ if(new ObjectID(id) === id){ return true } else { return false } } else { return false } }
Jackson Vaughan

그런 식으로 작동하거나 ObjetcId의 toString 함수를 사용하여 문자열 비교.
Andy Macleod

2
실제로 @JacksonVaughan 대답이 거의 맞습니다. 새 ObjectID (id)를 다른 문자열과 비교하기 때문에 문자열로 변환하는 String ()이 누락되었습니다. 여기에 완전한 정답이 있습니다. 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 } }
marcvander

1
@marcvander 나를 보자 es6쓸어 당신을 위해 :isObjectIdValid = id => ObjectId.isValid(id) ? String(new ObjectId(id) === id) ? true : false : false;
Rod911

82

정규 표현식을 사용하여 테스트 할 수 있습니다.

CoffeeScript

if id.match /^[0-9a-fA-F]{24}$/
    # it's an ObjectID
else
    # nope

자바 스크립트

if (id.match(/^[0-9a-fA-F]{24}$/)) {
    // it's an ObjectID    
} else {
    // nope    
}

1
흠 이것은 비 objectId 와도 일치 할 수 있습니다. 가장 좋은 방법은 사양 및 정규식을 기반으로 유효성 검사기를 구축하거나 특정 부분을 지정하거나 새로운 objectid를 만들고 가능한 경우 catch 블록을 수용하는 것입니다.
Sammaye

2
@Sammaye BSON ObjectID 생성자 에서 사용하는 것과 동일한 유효성 검사입니다 . 일치하는 비 ObjectID 문자열의 예를 제공 할 수 있습니까?
JohnnyHK dec.

와우, 나는 그것이 오는 것을 보지 못했습니다. IE에서 숫자와 문자를 가지고 잘 어떤 24 문자열,lol456712bbfghLLsdfr
Sammaye

13
@Sammaye 그러나 그것은 유효한 ObjectID이므로 일치해야합니다.
JohnnyHK

1
아마 올바른 방법으로, 공식적으로 몽구스에 의해 제안 github.com/Automattic/mongoose/issues/...
Akarsh Satija

10

나는 과거에 이것을하기 위해 네이티브 노드 mongodb 드라이버를 사용했다. isValid 메소드는 값이 유효한 BSON ObjectId인지 확인합니다. 여기에서 설명서를 참조하십시오.

var ObjectID = require('mongodb').ObjectID;
console.log( ObjectID.isValid(12345) );

작동하지 않는 것 같으며 위의 임의의 숫자에 대해 true를 반환합니다.
Dan Ochiana 2017 년

1
나는 그것이 ObjectId아니 어야하기 때문에 그럴 가능성이 가장 높다고 생각합니다 ObjectID. :)
Ken Hoff

이 대답을 받아 들여야합니다. 몽구스는 필요 없습니다
FH

5

Mongoose를 사용하는 경우 mongoose 빌트인 isValidObjectId를 사용하여 문자열이 12 바이트인지 아니면 24 진수 문자열인지 테스트 할 수 있습니다 .

mongoose.isValidObjectId (string)는 true / false를 반환합니다.

이것은 승인 된 솔루션에서 제공하는 업그레이드 된 솔루션 입니다.


진지하게,이 일에 투표합시다. 도서관이 이에 대한 지원을 제공하지 않았을 때 이전에 받아 들여진 대답은 훌륭했지만 지금은 그렇습니다. 우회하는 것은 구현 세부 사항에 의존하는 해킹입니다.
lance.dolan

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;
}

3

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

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

1

가장 쉬운 방법은 기본적으로 try and catch 서비스에서 ObjectId 메서드를 래핑하는 것입니다. 그런 다음 메서드를 직접 사용하는 대신이 서비스를 사용하여 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 또는 빈 props를 보내서 새로 생성 된 ID를 얻을 수도 있습니다.


1

문자열이 유효한 Mongo ObjectId인지 확인하는 가장 간단한 방법은 mongodb 모듈을 사용하는 것입니다.

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

if(ObjectID.isValid(777777777777777)){
   console.log("Valid ObjectID")
}

1

다음은 ObjectId isValid메서드로 확인 new ObjectId(id)하고 동일한 값을 반환 하는지 여부를 확인하는 함수입니다 . isValid혼자서 충분하지 않은 이유는 Andy Macleod가 선택한 답변에 잘 설명되어 있습니다.

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;
}

리뷰 감사합니다. 설명을 업데이트했습니다
AliAvci

2
이것은 문자열과 객체 ID를 엄격하게 비교하기 때문에 작동하지 않습니다. double equals로 업데이트하십시오.
마티아 Rasulo

0

16 진수 문자열이있는 경우 다음을 사용할 수 있습니다.

ObjectId.isValid(ObjectId.createFromHexString(hexId));

0

@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
}

0

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');
}

0

에서 솔루션 대답 앤디 맥 레오는 말했다 :

나를 위해 일한 것은 문자열을 objectId로 캐스팅 한 다음 원래 문자열이 objectId의 문자열 값과 일치하는지 확인하는 것입니다.

new ObjectId('timtamtomted'); //616273656e6365576f726b73
new ObjectId('537eed02ed345b2e039652d2') //537eed02ed345b2e039652d2

유효한 ID는 ObjectId로 캐스트 될 때 변경되지 않지만 false valid를 가져 오는 문자열은 objectId로 캐스트 될 때 변경되기 때문에 작동합니다.

이 접근 방식의 구현은 전달 된 값이 유효 ObjectId하고 stringObjectId(객체) 값 모두에서 작동하는지 확인하는 함수입니다 . 다음과 같이 보일 것입니다.

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;
}

0

@ ross-u 대답은 놀랍습니다.

전체 유효성 검사를 인라인으로 수행하는 방법을 연결했습니다.

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

이중 등호 new ObjectId()는 문자열을 반환하지 않으며 엄격한 비교는 일반 문자열과 비교할 때 false를 반환하므로 매우 중요 합니다.

메소드는 mongoose요구 사항에 의해 노출 된 객체에서 구조화되었습니다.

const {
  Types: {
    ObjectId: { isValid },
    ObjectId
  }
} = require("mongoose");

-2

경고 : isValid 는 유효한 16 진수로 시작하는 임의의 12/24 길이 문자열에 대해 true 를 반환 합니다 . 현재 나는 이것이 더 나은 수표라고 생각합니다.

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


3
이것은로 평가 것입니다 true에 대한 'funky string'. 올바른 길이이고 16 진수로 시작하는 모든 문자열이이를 충족합니다.
JohnnyHK 2014
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.