Es scheint, dass Mongo das Einfügen von Schlüsseln mit einem Punkt (.) Oder einem Dollarzeichen ($) nicht zulässt. Als ich jedoch eine JSON-Datei importierte, die einen Punkt enthielt, funktionierte dies mit dem Mongoimport-Tool einwandfrei. Der Treiber beschwert sich über den Versuch, dieses Element einzufügen.
So sieht das Dokument in der Datenbank aus:
{
"_id": {
"$oid": "..."
},
"make": "saab",
"models": {
"9.7x": [
2007,
2008,
2009,
2010
]
}
}
Mache ich das alles falsch und sollte solche Hash-Maps nicht mit externen Daten (dh den Modellen) verwenden oder kann ich dem Punkt irgendwie entkommen? Vielleicht denke ich zu viel Javascript-ähnlich.
javascript
mongodb
nosql
Michael Yagudaev
quelle
quelle
Antworten:
MongoDB unterstützt keine Schlüssel mit einem Punkt darin, daher müssen Sie Ihre JSON-Datei vorverarbeiten, um sie vor dem Import zu entfernen / ersetzen, oder Sie müssen sich auf alle möglichen Probleme einstellen.
Es gibt keine Standardumgehung für dieses Problem. Der beste Ansatz hängt zu stark von den Besonderheiten der Situation ab. Ich würde jedoch nach Möglichkeit jeden Key-Encoder / Decoder-Ansatz vermeiden, da Sie die Unannehmlichkeiten weiterhin auf Dauer bezahlen werden, wenn eine JSON-Umstrukturierung vermutlich einmalige Kosten verursachen würde.
quelle
models
hier), und (c) wir müssen sie nicht nach dem Schlüsselnamen in Mongo abfragen. Ein Muster, für das ich mich entschieden habe, istJSON.stringify
dieses Feld beim Speichern und 'JSON.parse' beim Abrufen.Wie in anderen Antworten erwähnt MongoDB nicht erlaubt
$
oder.
Zeichen als Mapkeys wegen Beschränkungen für Feldnamen . Wie in Dollar Sign Operator erwähnt. Wenn Sie dieser Einschränkung jedoch entkommen, können Sie keine Dokumente mit solchen Schlüsseln einfügen , sondern sie nur aktualisieren oder abfragen.Das Problem beim einfachen Ersetzen
.
durch[dot]
oderU+FF0E
(wie an anderer Stelle auf dieser Seite erwähnt) ist, was passiert, wenn der Benutzer den Schlüssel rechtmäßig speichern möchte[dot]
oderU+FF0E
?Ein Ansatz, den der afMorphia-Treiber von Fantom verfolgt , besteht darin, Unicode-Escape-Sequenzen zu verwenden, die denen von Java ähnlich sind, aber sicherzustellen, dass das Escape-Zeichen zuerst maskiert wird. Im Wesentlichen werden die folgenden Zeichenfolgen ersetzt (*):
Ein umgekehrter Austausch erfolgt, wenn die Kartenschlüssel anschließend aus MongoDB gelesen werden .
Oder im Fantomcode :
Ein Benutzer muss sich solcher Konvertierungen nur bewusst sein, wenn er Abfragen für solche Schlüssel erstellt.
Da es üblich ist, zu
dotted.property.names
Konfigurationszwecken in Datenbanken zu speichern , ist dieser Ansatz meines Erachtens dem einfachen Verbot aller dieser Kartenschlüssel vorzuziehen.(*) afMorphia führt tatsächlich vollständige / ordnungsgemäße Unicode-Escape- Regeln aus, wie in der Unicode-Escape-Syntax in Java erwähnt, aber die beschriebene Ersetzungssequenz funktioniert genauso gut.
quelle
//g
, um alle Vorkommen zu ersetzen und nicht nur das erste. Auch die Verwendung der Äquivalente in voller Breite wie in Martin Konecnys Antwort scheint eine gute Idee zu sein. Schließlich reicht ein Backslash für die Codierung aus.key.replace(/\./g, '\uff0e').replace(/\$/g, '\uff04').replace(/\\/g, '\uff3c')
U+FF04
.In den Mongo-Dokumenten wird vorgeschlagen , illegale Zeichen wie
$
und.
durch ihre Unicode-Entsprechungen zu ersetzen .quelle
db.test.insert({"field\uff0ename": "test"})
Die neueste stabile Version (v3.6.1) der MongoDB unterstützt jetzt Punkte (.) In den Schlüsseln oder Feldnamen.
Feldnamen können jetzt Punkte (.) Und Dollarzeichen ($) enthalten
quelle
mongoClient.getDatabase("mydb").getCollection("test").insertOne(new Document("value", new Document("key.with.dots", "value").append("$dollar", "value")));
Die Verwendung von mongodb-driver.3.6.3 und MongoDB 3.6.3 schlägt fehl.mongodb-4.1.1
undpymongo-3.7.1
. Ich kann Dokumente mit Schlüsseln mit.
Robomongo hinzufügen, aber nicht mitpymongo
, es wird immer noch ausgelöst.InvalidDocument: key '1.1' must not contain '.'
Ich wünschte, es wäre inzwischen behoben worden ...Eine Lösung, mit der ich gerade zufrieden bin, besteht darin, den Schlüsselnamen und den Wert in zwei separate Felder aufzuteilen. Auf diese Weise kann ich die Charaktere exakt gleich halten und mir keine Sorgen über diese Alpträume machen. Das Dokument würde folgendermaßen aussehen:
Sie können dies immer noch einfach genug abfragen, indem Sie
find
in den Feldern keyName und keyValue einen Wert eingeben .Also statt:
was nicht wirklich wie erwartet funktionieren würde, würden Sie ausführen:
und es wird das erwartete Dokument zurückgeben.
quelle
Sie können versuchen, anstelle des Werts einen Hash im Schlüssel zu verwenden und diesen Wert dann im JSON-Wert zu speichern.
Sie würden dann später mit dem Hash auf die Modelle zugreifen.
quelle
Es wird jetzt unterstützt
Ab MongoDb 3.6 werden sowohl Punkte als auch Dollar in Feldnamen unterstützt. Siehe unten JIRA: https://jira.mongodb.org/browse/JAVA-2810
Ein Upgrade Ihres Mongodb auf 3.6+ klingt nach dem besten Weg.
quelle
Aus den MongoDB-Dokumenten "the '." Zeichen darf nirgendwo im Schlüsselnamen erscheinen ". Es sieht so aus, als müssten Sie sich ein Kodierungsschema einfallen lassen oder darauf verzichten.
quelle
Sie müssen den Schlüsseln entkommen. Da es den Anschein hat, dass die meisten Menschen nicht wissen, wie sie Strings richtig entkommen können, sind hier die Schritte:
Denken Sie auch daran, dass Mongo auch nicht zulässt, dass Schlüssel mit '$' beginnen, sodass Sie dort etwas Ähnliches tun müssen
Hier ist ein Code, der das macht:
quelle
Eine späte Antwort, aber wenn Sie Spring und Mongo verwenden, kann Spring die Konvertierung für Sie verwalten
MappingMongoConverter
. Es ist die Lösung von JohnnyHK, wird aber von Spring gehandhabt.Wenn Ihr gespeicherter Json ist:
Durch den Frühling (MongoClient) wird es gelesen als:
quelle
Ich verwende das folgende Escapezeichen in JavaScript für jeden Objektschlüssel:
Was ich daran mag, ist, dass es nur
$
am Anfang ersetzt wird und keine Unicode-Zeichen verwendet, deren Verwendung in der Konsole schwierig sein kann._
ist für mich viel lesbarer als ein Unicode-Zeichen. Es ersetzt auch nicht einen Satz von Sonderzeichen ($
,.
) durch einen anderen (Unicode). Aber richtig entkommt mit traditionellen\
.quelle
Nicht perfekt, funktioniert aber in den meisten Situationen: Ersetzen Sie die verbotenen Zeichen durch etwas anderes. Da es sich um Schlüssel handelt, sollten diese neuen Zeichen ziemlich selten sein.
Hier ist ein Test:
und die Ergebnisse - beachten Sie, dass die Werte nicht geändert werden:
quelle
Es gibt eine hässliche Möglichkeit, es abzufragen. Es wird nicht empfohlen, es in der Anwendung und nicht für Debug-Zwecke zu verwenden (funktioniert nur bei eingebetteten Objekten):
quelle
Wie bereits von einem anderen Benutzer erwähnt, kann das Codieren / Decodieren in Zukunft problematisch werden. Daher ist es wahrscheinlich einfacher, alle Schlüssel mit einem Punkt zu ersetzen. Hier ist eine rekursive Funktion, die ich gemacht habe, um Schlüssel durch '.' Zu ersetzen. Vorkommen:
Sie können diesen Code ändern, um auch '$' zu ersetzen, da dies ein weiteres Zeichen ist, das Mongo in einem Schlüssel nicht zulässt.
quelle
Für PHP ersetze ich den HTML-Wert für den Zeitraum. Das ist
"."
.Es speichert in MongoDB wie folgt:
und der PHP-Code ...
quelle
Mit Lodash-Paaren können Sie Änderungen vornehmen
in
mit
quelle
Sie können es so speichern, wie es ist, und danach in hübsch konvertieren
Ich habe dieses Beispiel auf Livescript geschrieben. Sie können die Website livingcript.net verwenden, um sie zu bewerten
Es wird produzieren
quelle
Geben Sie meinen Tipp: Sie können JSON.stringify zum Speichern von Object / Array verwenden, das den Schlüsselnamen enthält, der Punkte enthält, und dann die Zeichenfolge mit JSON.parse in Object analysieren, um sie beim Abrufen von Daten aus der Datenbank zu verarbeiten
Eine weitere Problemumgehung: Restrukturieren Sie Ihr Schema wie folgt:
quelle
Die neueste MongoDB unterstützt Schlüssel mit einem Punkt, der Java MongoDB-Treiber wird jedoch nicht unterstützt. Damit es in Java funktioniert, habe ich Code aus dem Github-Repo des Java-Mongo-Treibers abgerufen und entsprechende Änderungen an der Funktion isValid Key vorgenommen. Daraus wurde ein neues JAR erstellt, das jetzt verwendet wird.
quelle
Ersetzen Sie den Punkt (
.
) oder den Dollar ($
) durch andere Zeichen, die im realen Dokument niemals verwendet werden. Stellen Sie beim Abrufen des Dokuments den Punkt (.
) oder den Dollar ($
) wieder her. Die Strategie hat keinen Einfluss auf die vom Benutzer gelesenen Daten.Sie können das Zeichen aus allen Zeichen auswählen .
quelle
Das Seltsame ist, dass ich mit Mongojs ein Dokument mit einem Punkt erstellen kann, wenn ich die _id selbst setze. Ich kann jedoch kein Dokument erstellen, wenn die _id generiert wird:
Funktioniert:
Funktioniert nicht:
Ich dachte zuerst, dass das Aktualisieren eines Dokuments mit einem Punktschlüssel auch funktioniert, aber es identifiziert den Punkt als Unterschlüssel!
Wenn ich sehe, wie Mongojs mit dem Punkt (Unterschlüssel) umgehen, werde ich sicherstellen, dass meine Schlüssel keinen Punkt enthalten.
quelle
Entfernen Sie wie das, was @JohnnyHK erwähnt hat, Satzzeichen oder '.' von Ihren Schlüsseln, weil es viel größere Probleme verursacht, wenn sich Ihre Daten in einem größeren Datensatz ansammeln. Dies führt zu Problemen, insbesondere wenn Sie Aggregatoperatoren wie $ merge aufrufen, bei denen auf Schlüssel zugegriffen und diese verglichen werden müssen, wodurch ein Fehler ausgelöst wird. Ich habe es auf die harte Tour gelernt, bitte nicht wiederholen für diejenigen, die anfangen.
quelle
/home/user/anaconda3/lib/python3.6/site-packages/pymongo/collection.py
Fand es in Fehlermeldungen. Wenn Sie verwenden
anaconda
(suchen Sie die entsprechende Datei, falls nicht), ändern Sie einfach den Wert voncheck_keys = True
inFalse
in der oben angegebenen Datei. Das wird funktionieren!quelle