문자열이 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하고 string및 ObjectId(객체) 값 모두에서 작동하는지 확인하는 함수입니다 . 다음과 같이 보일 것입니다.

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.