Einführung
FIELDNOTE verleiht kleine Ausrüstungssets. Sein übernommener MongoDB-Katalog enthält nützliche Bestandszahlen neben alten Zeichenfolgen und unklaren Werten. Eine bekannte Anzahl von 0 bedeutet, dass ein Set nicht verfügbar ist; eine fehlende Anzahl bedeutet, dass das Geschäft es nicht weiß. Beides in 0 umzuwandeln, würde ein Datenproblem verbergen. Deine Aufgabe ist es, diese Fälle zu trennen und unzuverlässige Datensätze für eine spätere Lieferantenprüfung aufzubewahren.
Du speicherst eine wiederverwendbare Klassifizierungsrichtlinie und ein Quarantäneskript, das das vollständige Originaldokument bewahrt, bevor es aus der aktiven Collection entfernt wird. Du benötigst grundlegende Terminalnavigation und Vertrautheit mit MongoDB-Dokumenten, verschachtelten Feldern, find und gewöhnlichen Aktualisierungen. Die hier verwendeten JavaScript-Konstrukte, Schemaregeln und BSON-Details werden vor der Verwendung erklärt. MongoDB, seine Shell und synthetische Katalogdaten sind vorbereitet. Verwende durchgehend Terminal. Die Dauer ist eine Autorenschätzung einschließlich Lesen und gewöhnlicher Fehler.
Verfasse policy.js und quarantine.js unter /home/labex/project/catalog-desk. Bewahre jede ursprüngliche ID, jedes vollständige ursprüngliche Feld und dessen Typ, unbeteiligte Erweiterungen, die Collection-Identität und bereitgestellte Werkzeuge. Lass gültige und reparierbare Datensätze in diesem Lab unverändert. Entferne/erstelle Collections nicht neu und überschreibe kein bestehendes Quarantäneoriginal. Arbeite nur an diesem Kurskatalog. Dies ist ein kontrolliertes Wartungsfenster ohne gleichzeitige Schreiber; Kopie und Löschung eines Datensatzes sind separate Operationen, keine Transaktion über den gesamten Katalog.
Den übernommenen Katalog lesen und klassifizieren
In diesem Schritt liest du einen gewöhnlichen verwendbaren Datensatz, unterscheidest gespeicherte Bestandstypen und speicherst eine ausdrückliche Klassifizierungsrichtlinie. Beginne in Terminal. cd wechselt das Verzeichnis; dieser absolute Pfad hilft auch nach einem Wechsel in das falsche Verzeichnis:
cd /home/labex/project/catalog-desk
./catalog ist das bereitgestellte Verbindungsprogramm in diesem Verzeichnis; ./ wählt die lokale ausführbare Datei. Sein Befehl show liest tatsächlich gespeicherte Dokumente. Übergib ihm eine Dokument-ID:
./catalog show KIT-101
Achte auf name: "Tripod", stock.rack: "A" und stock.available mit "$numberInt": "12". Die Ausgabe verwendet kanonisches Extended JSON: eine Textdarstellung mit ausdrücklichen BSON-Typkennzeichnungen. BSON ist MongoDBs gespeichertes Dokumentformat. $numberInt kennzeichnet eine 32-Bit-Ganzzahl; $numberLong kennzeichnet eine 64-Bit-Ganzzahl. Diese Kennzeichnungen in der Ausgabe beschreiben gespeicherte Zahlen, keine gewöhnlichen verschachtelten Bestandsfelder, die du ergänzen sollst.
Das Geschäft akzeptiert beide Ganzzahltypen für eine verfügbare Anzahl zwischen 0 und 50 einschließlich. Die ursprünglichen Felder stock.rack und supplier sind nützliche Informationen und müssen erhalten bleiben. _id identifiziert den Datensatz. Zwei Datensätze namens Tripod bleiben unterschiedliche Datensätze.
Prüfe den tatsächlichen serverseitigen Typ jeder Anzahl:
./catalog types
Dieses Leseprogramm verwendet MongoDBs Aggregationsausdruck $type auf stock.available. Seine Spalte actualType unterscheidet int, long, string, null, missing, array und double. double ist ein BSON-Gleitkommatyp; selbst ein ganzzahlig aussehender Double-Wert von 12 liegt außerhalb der Ganzzahlanforderungen dieses Geschäfts. missing bedeutet, dass das Feld nicht existiert; null bedeutet, dass es mit einem ausdrücklichen Nullwert existiert. Ein Array wie [12] ist keine einzelne skalare Anzahl.
Lies den vollständigen Katalog, um die Typen den ursprünglichen Datensätzen zuzuordnen:
./catalog show
Verwende diese Entscheidungstabelle vor dem Schreiben einer Abfrage:
| Gespeicherte Anzahl | Entscheidung in diesem Lab | Grund |
|---|---|---|
| Int32 12 oder Long 0 | Als verwendbar behalten | Akzeptierte skalare Ganzzahl, einschließlich des bekannten Werts 0 |
Zeichenfolge "12" oder "0" |
Für freigegebene Reparatur behalten | Kanonische Dezimaldarstellung im vereinbarten Bereich |
"12 kits", "012" oder "51" |
In Quarantäne verschieben | Unklare Bedeutung, nicht freigegebene Darstellung oder außerhalb des Bereichs |
| Null, fehlend, Array oder Double 12 | In Quarantäne verschieben | Erfüllt die vereinbarten Anforderungen an eine skalare Ganzzahl nicht |
Eine reparierbare Zeichenfolge darf nur die kanonischen ASCII-Ziffern für eine Zahl von 0 bis 50 enthalten: kein Vorzeichen, keine Leerzeichen, führende Null, Dezimalstelle oder Einheitenendung. Dies ist eine ausdrückliche Vereinbarung für diese übernommenen Daten, keine Zusage, dass jede zahlenähnliche Zeichenfolge sicher umgewandelt werden kann. Quarantäne bedeutet, ein vollständiges Original zur Prüfung zu bewahren; es bedeutet nicht, eine Ersatzanzahl zu erfinden.
Alle folgenden Befehle bleiben in diesem Terminal und Verzeichnis. Ist ein Dateiname falsch geschrieben, listet ls die tatsächlichen lokalen Namen auf. Korrigiere die Schreibweise und führe den Befehl erneut aus; ein Dateifehler ist keine Datenbankablehnung und erfordert kein Zurücksetzen der Umgebung.
Die Klassifizierungsrichtlinie speichern
Ein MongoDB-Selektor ist ein Dokument, das beschreibt, welche Datensätze passen. $jsonSchema prüft die Form und BSON-Typen eines Dokuments. required benennt Felder, die existieren müssen; es schließt für sich genommen den Wert null nicht aus. properties beschreibt jedes Feld, bsonType begrenzt dessen BSON-Typ, und minimum/maximum schließen ihre Grenzwerte ein. Die verschachtelte Regel stock verlangt separat available. Nicht genannte Felder bleiben erlaubt, sodass rack, supplier und spätere Erweiterungen erhalten bleiben können.
Verwende hier die skalare Typregel von JSON Schema. Ein gewöhnliches Abfrageprädikat wie {"stock.available": {$type: "int"}} kann ein Array mit einer Ganzzahl treffen. Dies würde die von diesem Katalog benötigte skalare Anzahl nicht belegen.
Du schreibst JavaScript für mongosh, die MongoDB-Shell. const gibt einem Wert einen Namen; = weist seinen Anfangswert zu, geschweifte Klammern bilden ein Objekt, eckige Klammern ein Array, und Kommas trennen Einträge. Text in Anführungszeichen ist eine Zeichenfolge; 0 und 50 ohne Anführungszeichen sind Zahlen. Ein Semikolon beendet eine Anweisung. schema beschreibt einen gesamten akzeptierten Datensatz, und valid verpackt es als MongoDB-Selektor.
Die Richtlinie für freigegebene Zeichenfolgen hat dieselbe Form, nur die Anzahlregel ändert sich. JSON.stringify wandelt dieses einfache Richtlinienobjekt in JSON-Text um, und JSON.parse liest eine separate Kopie; das Ändern der Kopie lässt die ursprüngliche Richtlinie dann unberührt. Diese Kopiermethode gilt für die einfache Richtlinie, nicht für das Bewahren gespeicherter BSON-Datensätze. stringSchema.properties.stock.properties.available erreicht die verschachtelte Regel, die ersetzt wird.
Das pattern ist ein regulärer Ausdruck für erlaubten Text. ^ verankert den Anfang und \z bedeutet das absolute Zeichenfolgenende; | trennt Alternativen, [1-9] erlaubt eine Ziffer von 1 bis 9, und [1-4][0-9] erlaubt zwei Ziffern von 10 bis 49. Zusammen mit 0 und 50 decken diese Alternativen exakt den freigegebenen Bereich ab. JavaScript-Zeichenfolgen verwenden einen umgekehrten Schrägstrich als Escape-Zeichen, daher schreibt die Quelle \\z, um \z an MongoDB zu übergeben. Dieser absolute Endanker lehnt auch einen abschließenden Zeilenumbruch ab; ein gewöhnlicher Endanker $ kann einen Treffer vor diesem Zeilenumbruch zulassen. $nor: [valid, repairable] wählt Datensätze aus, die keinem der beiden Selektoren entsprechen.
Erstelle die Richtliniendatei mit einem Here-Dokument. cat > policy.js schreibt den folgenden Text in die Datei und ersetzt ihren vorherigen Inhalt. Die Begrenzung <<'POLICY' in Anführungszeichen bewahrt Dollarzeichen und anderen JavaScript-Text wörtlich in der Shell. Schließe mit POLICY allein in einer Zeile ab. Kopiere den vollständigen Block:
cat > policy.js <<'POLICY'
const schema = {
bsonType: "object",
required: ["_id", "name", "stock"],
properties: {
_id: { bsonType: "string", minLength: 1 },
name: { bsonType: "string", minLength: 1 },
stock: {
bsonType: "object",
required: ["available"],
properties: {
available: { bsonType: ["int", "long"], minimum: 0, maximum: 50 }
}
}
}
};
const valid = { $jsonSchema: schema };
const stringSchema = JSON.parse(JSON.stringify(schema));
stringSchema.properties.stock.properties.available = {
bsonType: "string",
pattern: "^(0|[1-9]|[1-4][0-9]|50)\\z"
};
const repairable = { $jsonSchema: stringSchema };
const bad = { $nor: [valid, repairable] };
POLICY
Der bereitgestellte Klassifizierer wertet diese gespeicherte Datei unverändert unter einer schreibgeschützten Datenbankidentität aus. Er verwendet dann deine Selektoren valid, repairable und bad in tatsächlichen MongoDB-Abfragen:
./catalog classify policy.js
Prüfe die tatsächlichen Dokumentgruppen, nicht nur ihre Größen. valid sollte KIT-101 und KIT-102 enthalten, einschließlich des ursprünglichen Long-Werts 0. repairable sollte KIT-103 und KIT-104 mit unveränderten ursprünglichen Zeichenfolgen enthalten. outside sollte KIT-105 bis KIT-111 enthalten, einschließlich ursprünglichem null, fehlendem Feld, Array und Double. Die vollständige Erweiterung zur Lieferantenprüfung auf KIT-105 muss weiterhin sichtbar sein.
Erscheint ein JavaScript-Syntaxfehler, ist die Datei nicht als funktionierende Richtlinie akzeptiert. Führe das vollständige Here-Dokument erneut aus, um eine beschädigte Datei zu ersetzen, und starte den Klassifizierer erneut. Ein Syntaxfehler bezeichnet ein Datei-/Ausdrucksproblem; eine nicht verfügbare Datenbankverbindung ist ein anderer Fehler und bedeutet nicht, dass die Klassifizierung keine Treffer zurückgab. Dieser Klassifizierer hat keine Daten repariert oder entfernt.
Originale vor dem Entfernen unklarer Datensätze bewahren
In diesem Schritt speicherst du ein Quarantäneskript, beobachtest eine tatsächliche Unterbrechung nach seiner ersten Kopie und führst das unveränderte Skript erneut aus, um abzuschließen. Beginne in Terminal unter /home/labex/project/catalog-desk.
Jedes Quarantänedokument hat die ursprüngliche _id, ein original mit dem vollständigen gespeicherten Datensatz und reason: "outside-approved-catalog-contract". Der Grund beschreibt, warum eine Lieferantenprüfung nötig ist; er behauptet nicht, dass der Bestand 0 ist. Eine ursprüngliche Anzahl kann fehlen, null, ein Array oder ein anderer Typ sein, daher würde das Kopieren nur des angezeigten Werts oder nur des Namens Belege verlieren.
Es gibt eine weitere Grenze: Die Shell kann gespeicherte BSON-Zahlenwerte beim Lesen in gewöhnliche JavaScript-Zahlen umwandeln. Das Speichern einer ganzzahlig aussehenden JavaScript-Zahl kann dann Int32 erzeugen, obwohl das Original Double war. Verwende für jede Originalkopie und jeden Vergleich das dritte find-/findOne-Argument {promoteValues: false, bsonRegExp: true}. Es behält BSON-Zahlenwrapper und reguläre Ausdrücke bei, statt sie in JavaScript-Entsprechungen umzuwandeln. Das zweite Argument {} ist eine leere Projektion, die jedes Feld beibehält. EJSON.stringify(value, {relaxed: false}) erzeugt kanonisches Extended JSON aus diesen bewahrten Typen, sodass Double 12 und Int32 12 beim Vergleich unterschiedlich bleiben. Kanonischer EJSON-Text kann Typen nicht wiederherstellen, die bereits beim Lesen verloren gingen.
Die Skriptschleife liest die außerhalb liegende Gruppe einmal und behandelt jeden Datensatz separat. sort({_id: 1}) ergibt lesbare aufsteigende IDs, und toArray() sammelt die Ergebnisse. for (const doc of ...) wiederholt die eingeschlossenen Anweisungen für jedes Ergebnis. Die Upsert-Operation findet einen Quarantänedatensatz anhand seiner ursprünglichen ID; upsert: true erstellt ihn, falls er fehlt. $setOnInsert schreibt Original und Grund nur beim Erstellen dieses Datensatzes und lässt eine bestehende Kopie unberührt. findOne liest die gespeicherte Kopie zurück.
if prüft eine Bedingung. !== bedeutet ungleich und ||, dass eine der Bedingungen wahr ist. Ein anderes Original oder ein anderer Grund muss throw Error(...) auslösen; dies stoppt das Skript mit einem Exit-Status ungleich null vor dem Löschen dieses Quelldatensatzes. deleteOne entfernt nur die geprüfte Quell-ID. Frühere Datensätze können bereits abgeschlossen sein; dies sind einzelne Operationen, kein Alles-oder-nichts-Batch. Ohne gleichzeitige Schreiber bietet ein erfolgreicher vollständiger Vergleich vor jeder Löschung den hier verwendeten Wiederaufnahmeweg.
Schreibe das Skript. Das Here-Dokument QUARANTINE verwendet dieselbe wörtliche Schreibsyntax wie zuvor:
cat > quarantine.js <<'QUARANTINE'
const typed = { promoteValues: false, bsonRegExp: true };
for (const doc of db.equipment.find(bad, {}, typed).sort({_id: 1}).toArray()) {
db.quarantine.updateOne(
{_id: doc._id},
{$setOnInsert: {original: doc, reason: "outside-approved-catalog-contract"}},
{upsert: true}
);
const saved = db.quarantine.findOne({_id: doc._id}, {}, typed);
if (EJSON.stringify(saved.original, {relaxed: false}) !== EJSON.stringify(doc, {relaxed: false}) ||
saved.reason !== "outside-approved-catalog-contract") {
throw Error("Existing quarantine copy differs; keep source and investigate");
}
db.equipment.deleteOne({_id: doc._id});
}
QUARANTINE
Verwende zuerst die bereitgestellte Verbindung copy-only. Dies ist eine tatsächliche Datenbankidentität, die lesen und kopieren darf, aber nicht löschen. Das Programm wertet policy.js und dann quarantine.js unverändert in einem Shell-Aufruf aus. Erwarte einen nativen Autorisierungsfehler und einen Exit-Status ungleich null, wenn das Skript zum ersten Mal zu löschen versucht:
./catalog copy-only policy.js quarantine.js
Die Meldung enthält not authorized und einen Befehl delete auf equipment. Die Kopie war vor dieser Ablehnung erfolgreich. Lies beide tatsächlichen Datensätze:
./catalog archive KIT-105
./catalog show KIT-105
KIT-105 existiert nun an beiden Orten. Das Quarantäneoriginal muss seinen Bestandstext und die vollständige extension enthalten, einschließlich ihrer Typkennzeichnungen für Zahlen, Datum und ObjectId. Die aktive Quelle ist weiterhin intakt. Ein fehlgeschlagener Befehl bedeutet daher nicht, dass alle früheren Schreibzugriffe rückgängig gemacht wurden.
Führe exakt dieselben gespeicherten Dateien über die gewöhnliche Schreibverbindung des Kurses erneut aus:
./catalog run policy.js quarantine.js
Ein erfolgreiches Skript benötigt keine Ausgabe. Die erste vorhandene Kopie wird geprüft und bewahrt; ihre entsprechende Quelle wird entfernt. Die verbleibenden unklaren Datensätze werden nacheinander kopiert, geprüft und entfernt. Lies die tatsächlichen Ergebnisse:
./catalog show
./catalog archive
Der aktive Katalog sollte nur KIT-101 bis KIT-104 unverändert enthalten, einschließlich der beiden freigegebenen Zeichenfolgen, die auf Reparatur warten. Die Quarantäne sollte KIT-105 bis KIT-111 mit vollständigen Originaldokumenten und dem vereinbarten Grund enthalten. Insbesondere zeigt das ursprüngliche Double von KIT-109 weiterhin $numberDouble, und im Original von KIT-107 fehlt weiterhin das Feld available.
Führe die Migration erneut aus:
./catalog run policy.js quarantine.js
./catalog archive
Es sind keine außerhalb liegenden Datensätze mehr zu verschieben, daher bleiben die gespeicherten Originale gleich. Dies ist eine idempotente Wiederholung: Das Wiederholen einer abgeschlossenen Operation ändert ihr geschäftliches Ergebnis nicht. Auch eine Unterbrechung nach einer Kopie kann fortgesetzt werden, weil der Archivschlüssel eine doppelte Kopie verhindert und der Vergleich eine abweichende bestehende Kopie ablehnt. Erscheint dieser Konfliktfehler, bewahre Quelle und früheres Archiv zur Untersuchung; „behebe“ ihn nicht durch Überschreiben des Archivs oder Löschen der Quelle. Das Skript belegt keine Sicherheit gegen gleichzeitige Änderungen zwischen Lesen und Löschen und kann auch nicht den gesamten Batch zurückrollen.
Zusammenfassung
Du hast verwendbare ganzzahlige Bestandszahlen, ausdrücklich freigegebene Zeichenfolgen und unklare Datensätze mit einer wiederverwendbaren MongoDB-Richtlinie getrennt. Anschließend hast du vollständige typgetreue Originale vor dem Löschen ihrer aktiven Quellen bewahrt, einen tatsächlichen Teilfehler beobachtet und dasselbe gespeicherte Skript fortgesetzt. Der Katalog behält nun verwendbare und reparierbare Datensätze, während die Quarantäne Belege für die Lieferantenprüfung bewahrt. Umwandlung und Validierung künftiger Schreibzugriffe sind Thema der nächsten unabhängigen Einheit.



