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

Lesezeit: 7 Minuten

Benutzer-Avatar
Werden

Ich mache MongoDB-Lookups, indem ich eine Zeichenfolge in BSON umwandele. Kann ich feststellen, ob die Zeichenfolge, die ich habe, eine gültige ObjectID für Mongo ist, bevor ich die Konvertierung durchführe?

Hier ist das Coffeescript für meine aktuelle findByID-Funktion. Es funktioniert großartig, 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

Benutzer-Avatar
Andy MacLeod

Ich habe festgestellt, dass der Mongoose ObjectId-Validator funktioniert, um gültige Objekt-IDs zu validieren, aber ich habe einige Fälle gefunden, in denen ungültige IDs als gültig angesehen wurden. (z. B.: 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 das Umwandeln einer Zeichenfolge in eine Objekt-ID und das anschließende Überprüfen, ob die ursprüngliche Zeichenfolge mit dem Zeichenfolgenwert der Objekt-ID übereinstimmt.

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

Dies funktioniert, weil sich gültige IDs nicht ändern, wenn sie in eine ObjectId umgewandelt werden, aber eine Zeichenfolge, die ein falsches gültiges Ergebnis erhält, sich ändert, wenn sie in eine objectId umgewandelt wird.

  • Theoretisch könnten Sie diese beiden Methoden hinzufügen, um einen verdammt guten ObjectID-Validator zu generieren, das wird heute erledigt.

    – Antonius

    17. März 2016 um 17:38 Uhr


  • 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

    17. Mai 2019 um 12:01 Uhr

  • Eigentlich ist die Antwort von @JacksonVaughan fast richtig. Es fehlte ein String(), um die neue ObjectID(id) in einen String umzuwandeln, da wir sie mit einem anderen String vergleichen. Hier ist die vollkommen 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 } }

    – Marcvander

    15. Februar 2020 um 12:19 Uhr

  • @marcvander lass mich es6bestätige das für dich: isObjectIdValid = id => ObjectId.isValid(id) ? String(new ObjectId(id) === id) ? true : false : false;

    – Rod911

    9. Mai 2020 um 16:09 Uhr


  • Die Standardfunktion ist jetzt vorhanden (isValidObjectId), überprüfen Sie meine Antwort hier – stackoverflow.com/a/61779949/11896312

    – denk-ernst

    13. Mai 2020 um 16:34 Uhr

Benutzer-Avatar
Johnny HK

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    
}

  • Hmm, das könnte auch mit non-objectIds übereinstimmen, der beste Weg ist, entweder einen Validator zu bauen, der auf der Spezifikation und Regex seiner spezifischen Teile basiert, oder zu versuchen, eine neue objectid zu erstellen und einen Catch-Block unterzubringen, um ihn zu fangen, wenn er es kann.

    – Sammaye

    13. Dezember 2012 um 8:20 Uhr

  • @Sammaye Es ist dieselbe Validierung, die von der verwendet wird BSON ObjectID-Konstruktor. Können Sie mir ein Beispiel für eine Nicht-ObjectID-Zeichenfolge geben, die übereinstimmen würde?

    – JohnnyHK

    13. Dezember 2012 um 13:34 Uhr

  • Wow, das habe ich nicht kommen sehen. Nun, jede 24-stellige Zeichenfolge, die Zahlen und Buchstaben enthält, dh lol456712bbfghLLsdfr

    – Sammaye

    13. Dezember 2012 um 13:37 Uhr

  • @Sammaye Aber das ist eine gültige ObjectID, also sollte sie übereinstimmen.

    – JohnnyHK

    13. Dezember 2012 um 14:16 Uhr

  • Wahrscheinlich der richtige Weg, offiziell von Mungo vorgeschlagen github.com/Automattic/mongoose/issues/…

    – Akarsh Satija

    26. Dezember 2016 um 10:21 Uhr

Benutzer-Avatar
Jemand Besonderes

✅ Eingebaute Lösung isValidObjectId() > Mungo 5.7.12

Wenn Sie Mongoose verwenden, können wir mit testen, ob ein String aus 12 Bytes oder aus 24 Hexadezimalzeichen besteht Mungo eingebaut istValidObjectId.

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

🛑 ACHTUNG!

isValidObjectId() wird am häufigsten zum Testen einer erwarteten Objekt-ID verwendet, um zu vermeiden, dass Mongoose einen ungültigen Objekt-ID-Fehler auslöst.

Beispiel

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

Wenn Sie nicht bedingt testen, ob die erwartete Objekt-ID gültig ist, müssen Sie den Fehler abfangen.

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

Seit findOne({ _id: null }) und findOne({ _id: undefined }) sind vollständig gültige Abfragen (wirft keinen Fehler), isValidObjectId(undefined) und isValidObjectId(null) wird wahr zurückgeben.

🛑 ANMERKUNG 2!

123456789012 sieht möglicherweise nicht wie eine bson-Zeichenfolge aus, ist aber eine vollständig gültige ObjectID, da die folgende Abfrage nicht Fehler werfen. (Null zurückgeben, wenn kein Datensatz gefunden wird).

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

313233343536373839303132 kann wie eine 24-stellige Zeichenfolge aussehen (es ist der Hexadezimalwert von 123456789012), aber es ist auch eine gültige ObjectId, weil die folgende Abfrage nicht Fehler werfen. (null zurückgeben, wenn kein Datensatz gefunden wird)

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

Die folgenden sind ungültig (1 Zeichenkette weniger als die obigen Beispiele)

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

Format der ObjectId

ObjectIds sind klein, wahrscheinlich einzigartig, schnell zu generieren und geordnet. ObjectId-Werte sind 12 Byte lang und bestehen aus:

  • ein 4-Byte-Zeitstempelwert, der die Erstellung der ObjectId darstellt, gemessen in Sekunden seit der Unix-Epoche
  • ein 5-Byte Zufallswert einmal pro Vorgang generiert. Dies Zufallswert ist einzigartig für die Maschine und den Prozess.
  • ein 3-Byte-Inkrementierungszähler, initialisiert auf einen zufälligen Wert

Aufgrund des oben Gesagten ZufallswertObjekt Identifikation kann nicht berechnet werden. Es kann nur als 12-Byte-String oder 24-Zeichen-Hex-String erscheinen.

  • ernsthaft, lasst uns dieses Ding abstimmen. Die alte akzeptierte Antwort war großartig, als die Bibliothek dafür keine Unterstützung bot, aber jetzt tut sie es. Es zu umgehen ist ein Hack, der von Implementierungsdetails abhängt.

    – Lanze.dolan

    18. Dezember 2020 um 22:33 Uhr

  • Dies akzeptiert eine beliebige Zahl der Zeichenlänge 12 als gültige Objekt-ID. Gibt es eine Möglichkeit, nur nach Objekt-IDs mit 24 Zeichen zu suchen, die auch in einem akzeptierten Format, dh alphanumerisch, vorliegen? Mit akzeptiertem Format ist dies wie hier beschrieben gemeint docs.mongodb.com/manual/reference/method/ObjectId

    – Avani Khabiya

    12. August 2021 um 6:06 Uhr


  • Beachten Sie, dass die Objekt-ID einen zufälligen 5-Byte-Wert enthält. Mehr als oft nicht, isValidObjectId ist mehr als ausreichend, da Ihre Anfragen von Mongoose nicht abgelehnt werden. Wenn es sich um eine ungültige Objekt-ID handelt, gibt Mungo einen Fehler aus, wenn Ihr Schema eine Objekt-ID erfordert. Die Überprüfung auf validObjectID bedeutet, die Abfrage abzulehnen, bevor Ihr Mungo den Fehler auslöst.

    – Jemand Besonderes

    12. August 2021 um 9:12 Uhr


  • Beachten Sie, dass diese Funktion true zurückgibt, wenn die Eingabe nicht definiert ist. Dies ist möglicherweise nicht das, was Sie wollen.

    – Mihai

    23. November 2021 um 16:40 Uhr

  • Ja und nein. undefined kann einfach als gültige ObjectID behandelt werden, weil dies der Fall ist Model.find({ _id: undefined}), es wird kein Fehler ausgegeben. Während, wenn Sie dies tun Model.find({ _id: 'abc'}) (ungültige ObjectID), wird a ausgelöst Umwandlung in ObjectId fehlgeschlagen Error

    – Jemand Besonderes

    23. November 2021 um 20:21 Uhr

Ich habe dazu in der Vergangenheit den nativen Knoten-Mongodb-Treiber verwendet. Die isValid-Methode prüft, ob der Wert eine gültige BSON-ObjectId ist. Sehen Sie sich die Dokumentation hier an.

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

mongoose.Types.ObjectId.isValid(string) gibt immer True zurück, wenn string 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

Benutzer-Avatar
nzjoel

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

Es kann entweder eine Ganzzahl oder eine Zeichenfolge oder eine ObjectId annehmen und gibt eine gültige ObjectId zurück, 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;
}

Benutzer-Avatar
Pavneet Kaur

Der einfachste Weg, um zu überprüfen, ob die Zeichenfolge eine gültige Mongo ObjectId ist, ist die Verwendung mongodb Modul.

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

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

  • Es ist verrückt, wie beliebt Mongoose ist. Der Mongodb-Kerntreiber ist leistungsfähiger und in neueren Versionen mit POJO-Unterstützung ist Mongoose nur eine Schicht der Ineffizienz.

    – Robert

    11. März um 22:33 Uhr

  • Ja. Tatsächlich sind native Mongo-Abfragefunktionen viel schneller als die Verwendung von Mongoose-Funktionen.

    – Pavneet Kaur

    12. März um 12:23 Uhr

1242360cookie-checkKann ich feststellen, ob eine Zeichenfolge eine MongoDB-Objekt-ID ist?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy