Kann ich feststellen, ob eine Zeichenfolge eine MongoDB-Objekt-ID ist?

79

Ich mache MongoDB-Lookups, indem ich einen String in BSON konvertiere. Kann ich vor der Konvertierung feststellen, ob die Zeichenfolge, die ich habe, eine gültige ObjectID für Mongo ist?

Hier ist das Coffeescript für meine aktuelle findByID-Funktion. Es funktioniert gut, aber ich möchte nach einem anderen Attribut suchen, wenn ich feststelle, dass die Zeichenfolge keine ID ist.

db.collection "pages", (err, collection) ->
  collection.findOne
    _id: new BSON.ObjectID(id)
  , (err, item) ->
    if item
      res.send item
    else
      res.send 404
Wille
quelle
Im Moment funktioniert die Verwendung eines try catch-Blocks. Ist das die empfohlene Lösung?
Wird

Antworten:

139

Ich habe festgestellt, dass der mongoose ObjectId-Validator gültige objectIds validiert, aber ich habe einige Fälle gefunden, in denen ungültige IDs als gültig angesehen wurden. (zB: eine beliebige 12 Zeichen lange Zeichenfolge)

var ObjectId = require('mongoose').Types.ObjectId;
ObjectId.isValid('microsoft123'); //true
ObjectId.isValid('timtomtamted'); //true
ObjectId.isValid('551137c2f9e1fac808a5f572'); //true

Was für mich funktioniert hat, ist, eine Zeichenfolge in eine Objekt-ID umzuwandeln und dann zu überprüfen, ob die ursprüngliche Zeichenfolge mit dem Zeichenfolgenwert der Objekt-ID übereinstimmt.

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

Dies funktioniert, da sich gültige IDs nicht ändern, wenn sie in eine ObjectId umgewandelt werden. Eine Zeichenfolge, die eine falsche Gültigkeit erhält, ändert sich jedoch, wenn sie in eine objectId umgewandelt wird.

Andy Macleod
quelle
Theoretisch könnten Sie diese beiden Methoden hinzufügen, um einen verdammt guten ObjectID-Validator zu generieren.
Anthony
2
Also so etwas? function checkObjectIdValid(id){ if(ObjectID.isValid(id)){ if(new ObjectID(id) === id){ return true } else { return false } } else { return false } }
Jackson Vaughan
So etwas würde funktionieren oder ein String-Vergleich mit der toString-Funktion von ObjetcId.
Andy Macleod
2
Eigentlich ist @JacksonVaughan Antwort fast richtig. Es fehlte ein String (), um die neue ObjectID (ID) in einen String zu konvertieren, da wir sie mit einem anderen String vergleichen. Hier ist die richtige Antwort: 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 } }
Markvander
1
@marcvander lass mich es6das für dich isObjectIdValid = id => ObjectId.isValid(id) ? String(new ObjectId(id) === id) ? true : false : false;
tun
81

Sie können einen regulären Ausdruck verwenden, um dies zu testen:

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    
}
JohnnyHK
quelle
1
Hmm, dies könnte auch mit Nicht-Objekt-IDs übereinstimmen. Der beste Weg ist, entweder einen Validator basierend auf der Spezifikation zu erstellen und die spezifischen Teile neu zu formulieren oder zu versuchen, eine neue Objekt-ID zu erstellen und einen Catch-Block zu speichern, um zu fangen, wenn dies möglich ist.
Sammaye
2
@Sammaye Es ist dieselbe Validierung, die vom BSON ObjectID-Konstruktor verwendet wird . Können Sie mir ein Beispiel für eine Nicht-ObjectID-Zeichenfolge geben, mit der sie übereinstimmen würde?
JohnnyHK
Wow, das habe ich nicht kommen sehen. Nun, jede 24- lol456712bbfghLLsdfr
stellige
13
@Sammaye Aber das ist eine gültige ObjectID, also sollte sie übereinstimmen.
JohnnyHK
1
Wahrscheinlich der richtige Weg, offiziell vorgeschlagen von Mungo github.com/Automattic/mongoose/issues/…
Akarsh Satija
9

Ich habe in der Vergangenheit den Native Node Mongodb-Treiber verwendet, um dies zu tun. Die Methode isValid überprüft, ob der Wert eine gültige BSON-Objekt-ID ist. Siehe die Dokumentation hier.

var ObjectID = require('mongodb').ObjectID;
console.log( ObjectID.isValid(12345) );
cbaigorri
quelle
scheint nicht zu funktionieren, oben gibt true für eine Zufallszahl zurück.
Dan Ochiana
1
Ich denke, das ist am wahrscheinlichsten, weil es sein sollte ObjectId, nicht ObjectID. :)
Ken Hoff
4

Hier ist ein Code, den ich basierend auf der Antwort von @ andy-macleod geschrieben habe.

Es kann entweder eine int oder eine Zeichenfolge oder eine ObjectId annehmen und eine gültige ObjectId zurückgeben, wenn der übergebene Wert gültig ist, oder null, wenn er ungültig ist:

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;
}
nzjoel
quelle
3

Wenn Sie Mongoose verwenden, können Sie mithilfe von isValidObjectId testen, ob eine Zeichenfolge 12 Byte oder eine Zeichenfolge mit 24 Hex-Zeichen enthält .

mongoose.isValidObjectId (Zeichenfolge) gibt true / false zurück

Dies ist eine aktualisierte Lösung, die von einer akzeptierten Lösung bereitgestellt wird .

Jemand Besonderes
quelle
2

Die einzige Möglichkeit, die ich gefunden habe, besteht darin, eine neue ObjectId mit dem Wert zu erstellen, den ich überprüfen möchte. Wenn die Eingabe der Ausgabe entspricht, ist die ID gültig:

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
Daphoque
quelle
2

mongoose.Types.ObjectId.isValid (Zeichenfolge) gibt immer True zurück, wenn die Zeichenfolge 12 Buchstaben enthält

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
Sajag Porwal
quelle
1

Am einfachsten ist es, Ihre ObjectId-Methode in einen Try-and-Catch-Dienst einzuschließen. Dann verwenden Sie diesen Dienst, um Objecet-IDs zu verarbeiten, anstatt die Methode direkt zu verwenden:

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
}

Sie können auch null oder leere Requisiten senden, um eine neu generierte ID zu erhalten.

Raz
quelle
1

Der einfachste Weg, um zu überprüfen, ob die Zeichenfolge eine gültige Mongo ObjectId ist, ist die Verwendung des Mongodb- Moduls.

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

if(ObjectID.isValid(777777777777777)){
   console.log("Valid ObjectID")
}
Pavneet Kaur
quelle
1

Im Folgenden finden Sie eine Funktion, die sowohl mit der ObjectId- isValidMethode überprüft als auch überprüft , ob new ObjectId(id)derselbe Wert zurückgegeben wird. Der Grund dafür, isValidnicht genug allein zu sein, wird von Andy Macleod in der gewählten Antwort sehr gut beschrieben.

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
quelle
Vielen Dank für die Bewertung. Ich habe die Beschreibung aktualisiert
AliAvci
2
Dies funktioniert nicht, da Sie einen strengen Vergleich zwischen der Zeichenfolge und der Objekt-ID durchführen. Bitte aktualisieren Sie auf Double Equals.
Mattia Rasulo
0

Wenn Sie die Hex-Zeichenfolge haben, können Sie diese verwenden:

ObjectId.isValid(ObjectId.createFromHexString(hexId));
pkarc
quelle
0

Es hat eine Weile gedauert, bis ich eine gültige Lösung gefunden hatte, da die von @Andy Macleod vorgeschlagene Lösung zum Vergleichen des objectId-Werts mit einer eigenen Zeichenfolge den Express.js-Server zum Absturz brachte:

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

Ich habe nur einen einfachen Versuch verwendet, um dies zu lösen.

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
}
Vibhu
quelle
0

Verwenden Sie für Mungo die Funktion isValid (), um zu überprüfen, ob objectId gültig ist oder nicht

Beispiel:

var ObjectId = mongoose.Types.ObjectId;
if(ObjectId.isValid(req.params.documentId)){
   console.log('Object id is valid'); 
}else{
   console.log('Invalid Object id');
}
Om Sharma
quelle
0

In der Antwort der Lösung sagte Andy Macleod :

Was für mich funktioniert hat, ist, eine Zeichenfolge in eine Objekt-ID umzuwandeln und dann zu überprüfen, ob die ursprüngliche Zeichenfolge mit dem Zeichenfolgenwert der Objekt-ID übereinstimmt.

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

Dies funktioniert, da sich gültige IDs nicht ändern, wenn sie in eine ObjectId umgewandelt werden. Eine Zeichenfolge, die eine falsche Gültigkeit erhält, ändert sich jedoch, wenn sie in eine objectId umgewandelt wird.

Eine Implementierung dieses Ansatzes wäre eine Funktion, die prüft, ob der übergebene Wert gültig ist ObjectIdund mit beiden stringund ObjectId(Objekt-) Werten arbeitet. Es würde ungefähr so ​​aussehen:

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;
}
ross-u
quelle
0

@ Ross-U Antwort ist einfach unglaublich.

Ich habe die Methoden verkettet, um eine vollständige Validierung inline durchzuführen:

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

Beachten Sie das doppelte Gleichheitszeichen, das als SEHR wichtig ist new ObjectId() es keinen String und ein strikter Vergleich im Vergleich zu einem normalen String (den ich in meiner Logik hatte) false zurückgibt.

Die Methoden wurden von dem mongooseObjekt zerstört, das durch die Anforderung freigelegt wurde:

const {
  Types: {
    ObjectId: { isValid },
    ObjectId
  }
} = require("mongoose");
Mattia Rasulo
quelle
-2

Warnung: isValid gibt true für beliebige Zeichenfolgen mit einer Länge von 12/24 zurück, die mit einer gültigen Hex-Ziffer beginnen. Derzeit denke ich, dass dies eine bessere Überprüfung ist:

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

iss42
quelle
3
Dies würde sich für truez 'funky string'. Jede Zeichenfolge, die die richtige Länge hat und mit einer hexadezimalen Ziffer beginnt, erfüllt diese.
JohnnyHK