105 votes

MongoDB point (.) dans le nom de la clé

Il semble que Mongo ne permette pas l'insertion de clés avec un point (.) ou un signe dollar ($). Cependant, lorsque j'ai importé un fichier JSON contenant un point à l'aide de l'outil mongoimport, tout s'est bien passé. Le pilote se plaint d'essayer d'insérer cet élément.

Voici à quoi ressemble le document dans la base de données :

{
    "_id": {
        "$oid": "..."
    },
    "make": "saab",
    "models": {
        "9.7x": [
            2007,
            2008,
            2009,
            2010
        ]
    }
}

Est-ce que je m'y prends mal et ne devrais pas utiliser des cartes de hachage de cette manière avec des données externes (c'est-à-dire les modèles) ou puis-je échapper au point d'une manière ou d'une autre ? Je pense peut-être trop à la manière de Javascript.

91voto

JohnnyHK Points 61191

MongoDB ne prend pas en charge touches avec un point Vous devrez donc prétraiter votre fichier JSON pour les supprimer/remplacer avant de l'importer ou vous vous exposez à toutes sortes de problèmes.

Il n'y a pas de solution standard à ce problème, la meilleure approche dépend trop des spécificités de la situation. Mais j'éviterais si possible toute approche de type encodeur/décodeur de clé, car vous continuerez à en payer les inconvénients à perpétuité, alors qu'une restructuration JSON ne représenterait vraisemblablement qu'un coût unique.

27voto

Steve Eynon Points 1175

Comme mentionné dans d'autres réponses, MongoDB ne permet pas de $ o . comme clés de carte en raison de restrictions sur les noms de champs . Cependant, comme mentionné dans L'opérateur du signe du dollar s'échappe cette restriction ne vous empêche pas de en insérant des documents avec de telles clés, il vous empêche simplement de les mettre à jour ou de les interroger.

Le problème du simple remplacement . con [dot] o U+FF0E (comme mentionné ailleurs sur cette page) est de savoir ce qui se passe lorsque l'utilisateur veut légitimement stocker la clé [dot] o U+FF0E ?

Une approche qui Fantom's conducteur afMorphia consiste à utiliser des séquences d'échappement unicode similaires à celles de Java, mais en s'assurant que le caractère d'échappement est échappé en premier. En substance, les remplacements de chaînes de caractères suivants sont effectués (*) :

\  -->  \\
$  -->  \u0024
.  -->  \u002e

Un remplacement inverse est effectué lorsque les clés de la carte sont lues ultérieurement. de MongoDB.

Ou dans Fantôme code :

Str encodeKey(Str key) {
    return key.replace("\\", "\\\\").replace("\$", "\\u0024").replace(".", "\\u002e")
}

Str decodeKey(Str key) {
    return key.replace("\\u002e", ".").replace("\\u0024", "\$").replace("\\\\", "\\")
}

Le seul moment où l'utilisateur doit être conscient de ces conversions est lorsqu'il construit des requêtes pour ces clés.

Étant donné qu'il est courant de stocker dotted.property.names dans les bases de données à des fins de configuration, je pense que cette approche est préférable à l'interdiction pure et simple de toutes ces clés de carte.

(*) afMorphia exécute effectivement les règles d'échappement unicode complètes et correctes, comme indiqué dans le document Syntaxe d'échappement Unicode en Java mais la séquence de remplacement décrite fonctionne tout aussi bien.

19voto

Martin Konecny Points 7328

El Documentation sur Mongo suggère de remplacer les caractères illégaux tels que $ y . avec leurs équivalents unicode.

Dans ces situations, les clés devront remplacer les caractères réservés $ et . N'importe quel caractère est suffisant, mais envisagez d'utiliser les équivalents Unicode pleine largeur : U+FF04 (c'est-à-dire "$") et U+FF0E (c'est-à-dire ".").

19voto

h4ck3d Points 1459

La dernière version stable (v3.6.1) de MongoDB supporte désormais les points (.) dans les clés ou les noms de champs.

Les noms de champ peuvent contenir des points (.) et des caractères dollar ($) maintenant

13voto

Steve Points 1380

Une solution que je viens de mettre en œuvre et dont je suis très satisfait consiste à répartir le nom et la valeur de la clé dans deux champs distincts. De cette façon, je peux conserver exactement les mêmes caractères et ne pas m'inquiéter des cauchemars de l'analyse syntaxique. Le document ressemblerait à ça :

{
    ...
    keyName: "domain.com",
    keyValue: "unregistered",
    ...
}

Vous pouvez toujours interroger cette question assez facilement, juste en faisant un find sur les champs Nom de la clé et valeur de la clé .

Donc, au lieu de :

 db.collection.find({"domain.com":"unregistered"})

ce qui ne fonctionnerait pas comme prévu, vous vous exécuteriez :

db.collection.find({keyName:"domain.com", keyValue:"unregistered"})

et il retournera le document attendu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X