web-dev-qa-db-fra.com

Stocker null vs ne pas stocker du tout la clé dans MongoDB

Il me semble que lorsque vous créez un document Mongo et que vous avez un champ {key, value} qui n'a parfois pas de valeur, vous avez deux options:

  1. Écrire {key, null} c'est-à-dire écrire une valeur nulle dans le champ
  2. Ne stockez pas du tout la clé dans ce document

Les deux options sont facilement interrogables, dans l'une vous interrogez sur {key : null} et l'autre que vous recherchez {key : {$exists : false}}.

Je ne peux pas vraiment penser à des différences entre les deux options qui auraient un impact dans un scénario d'application (sauf que l'option 2 a un peu moins de stockage).

Quelqu'un peut-il me dire s'il y a des raisons pour lesquelles l'une préférerait l'une des deux approches à l'autre, et pourquoi?

MODIFIER

Après avoir posé la question, il m'est également venu à l'esprit que les index peuvent se comporter différemment dans les deux cas, c'est-à-dire qu'un index clairsemé peut être créé pour l'option 2.

42
Zaid Masud

En effet, vous avez également une troisième possibilité: key: "" (valeur vide)

Et vous oubliez une spécificité de la valeur nulle. Requête sur key: null vous récupérera tous les documents où la clé est nulle o où la clé n'existe pas.

Lorsqu'une requête sur $exists:false récupérera uniquement les documents où la clé de champ n'existe pas.

Pour revenir à votre question exacte, cela dépend de vos requêtes et des données représentées. Si vous devez conserver cela, par exemple, un utilisateur définit une valeur puis la désactive, vous devez laisser le champ nul ou vide. Si vous n'en avez pas besoin, vous pouvez supprimer ce champ.

35
AlphaB

Notez que, comme MongoDB n'utilise pas la compression du dictionnaire de noms de champs, field:null consomme de l'espace disque et de la RAM, tout en ne stockant aucune clé ne consomme pas de ressources.

16
Samuel García

Cela se résume vraiment à:

  • Votre scénario
  • Votre manière d'interroger
  • Votre index a besoin
  • Votre langue

J'ai personnellement choisi de stocker les clés nulles. Cela facilite beaucoup l'intégration dans mon application. J'utilise PHP avec Active Record et les valeurs nulles uisng me facilitent la vie car je n'ai pas à mettre l'accent sur la dépendance des champs sur l'application. De plus, je n'ai pas besoin de rendre complexe code pour faire face à la magie pour définir des variables inexistantes.

Personnellement, je ne stockerais pas de valeur vide comme "" car si vous ne faites pas attention, vous pourriez avoir deux valeurs vides null et "" et vous aurez alors le temps de poser des questions spécifiques. Donc, je préfère personnellement null pour les valeurs vides.

En ce qui concerne l'espace et l'index: cela dépend du nombre de lignes qui pourraient ne pas avoir cette colonne, mais je doute que vous remarquerez vraiment l'augmentation de la taille de l'index en raison de quelques documents supplémentaires avec null in. Je veux dire que la différence de stockage est mineute surtout si le correspondant le nom de la clé est également petit. Cela vaut également pour les grandes configurations.

Je ne suis vraiment pas sûr de l'utilisation de l'index entre $exists et null cependant null pourrait être une méthode plus standardisée pour interroger l'existence car rappelez-vous que MongoDB est sans schéma, ce qui signifie que vous n'avez pas besoin d'avoir ce champ dans le document qui produit à nouveau deux valeurs vides: inexistantes et null. Il vaut donc mieux choisir l'un ou l'autre.

Je choisis null.

7
Sammaye

Un autre point que vous voudrez peut-être considérer est lorsque vous utilisez des outils OGM comme Hibernate OGM.

Si vous utilisez Java, Hibernate OGM prend en charge la norme JPA. Donc, si vous pouvez écrire une requête JPQL, vous seriez théoriquement facile si vous souhaitez passer à une autre banque de données NoSQL qui est prise en charge par l'outil OGM.

JPA ne définit pas d'équivalent pour $ existe dans Mongo. Donc, si vous avez des attributs facultatifs dans votre collection, vous ne pouvez pas écrire un JPQL approprié pour le même. Dans un tel cas, si la valeur de l'attribut est stockée en tant que NULL, il est toujours possible d'écrire une requête JPQL valide comme ci-dessous.

SELECT p FROM pppoe p where p.logout IS null;
2
Vinod