Kann ich feststellen, ob eine Zeichenfolge eine MongoDB-Objekt-ID ist?
Lesezeit: 7 Minuten
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
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
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.
Wenn Sie Mongoose verwenden, können wir mit testen, ob ein String aus 12 Bytes oder aus 24 Hexadezimalzeichen besteht Mungo eingebautistValidObjectId.
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.
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).
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)
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
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;
}
Pavneet Kaur
Der einfachste Weg, um zu überprüfen, ob die Zeichenfolge eine gültige Mongo ObjectId ist, ist die Verwendung mongodb Modul.
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
12423600cookie-checkKann ich feststellen, ob eine Zeichenfolge eine MongoDB-Objekt-ID ist?yes