MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Spring Data Mongo - appliquer des champs de combinaison uniques dans le document intégré

Dans MongoDB, un index unique garantit qu'une valeur particulière dans un champ n'est pas présente dans plus d'un document. Ce ne sera pas garantir qu'une valeur est unique dans un tableau au sein d'un même document. Ceci est expliqué ici dans le manuel de MongoDB où il est question des index multiclés uniques.

Ainsi, un index unique ne satisfera pas votre exigence. Cela empêchera les documents séparés de contenir des combinaisons en double, mais cela permettra toujours à un seul document de contenir des valeurs en double dans un tableau.

La meilleure option consiste à modifier votre modèle de données afin de diviser le tableau d'objets technologyEmployeeRef en documents distincts. Le diviser en documents séparés vous permettra d'utiliser un index unique pour renforcer l'unicité.

L'implémentation particulière à adopter pour ce changement de modèle de données dépendra de votre modèle d'accès (qui sort du cadre de cette question).

Pour ce faire, vous pouvez notamment créer une collection TechnologyEmployee contenant tous les champs qui existent actuellement dans le tableau technologyEmployeeRef. De plus, cette collection TechnologyEmployee aurait un champ, tel que email, qui vous permettrait de l'associer à un document de la collection Employee.

Exemple de document d'employé

{
  ....
  ....
  "firstName" : "John",
  "lastName" : "Doe",
  "email" : "[email protected]",
  .....
  .....
  .....
}

Exemple de document EmployeeTechnology

{
  "email" : "[email protected]",
  "technologyCd" : "Java",
  "technologyName" : "Java8",
  ....
  .....
  "status" : "A"
}

Index dans la collection EmployeeTechnology

{'email' : 1, 'technologyCd' : 1}, {unique: true}

L'inconvénient de cette approche est que vous auriez besoin de lire à partir de deux collections pour avoir toutes les données. Cet inconvénient peut ne pas être un gros problème si vous avez rarement besoin de récupérer les données des deux collections en même temps. Si vous avez besoin de toutes les données, cela peut être accéléré grâce à l'utilisation d'index. Avec les index, cela pourrait être accéléré grâce à l'utilisation de requêtes couvertes.

Une autre option consiste à dénormaliser les données. Pour ce faire, dupliquez les données des employés auxquelles vous devez accéder en même temps que les données de la technologie.

Exemples de documents

[
  {
    ....
    "firstName" : "John",
    "lastName" : "Doe",
    "email" : "[email protected]",
    .....
    "technologyCd" : "Java",
    "technologyName" : "Java8",
    ....
    "status" : "A"
  },
  {
    ....
    "firstName" : "John",
    "lastName" : "Doe",
    "email" : "[email protected]",
    .....
    "technologyCd" : "Spring",
    "technologyName" : "Spring Boot2",
    ....
    "status" : "A"
  }
]

Dans ce billet de blog MongoDB, ils disent que

Vous ne feriez cela que pour les champs qui sont lus fréquemment, lus beaucoup plus souvent qu'ils ne sont mis à jour, et où vous n'avez pas besoin d'une cohérence forte, car la mise à jour d'une valeur dénormalisée est plus lente, plus coûteuse et n'est pas atomique.

Ou, comme vous l'avez déjà mentionné, il peut être judicieux de laisser le modèle de données tel quel et d'effectuer la vérification de l'unicité du côté de l'application. Cela pourrait probablement vous offrir les meilleures performances de lecture, mais cela présente certains inconvénients. Tout d'abord, cela ralentira les opérations d'écriture car l'application devra exécuter certaines vérifications avant de pouvoir mettre à jour la base de données.

C'est peut-être peu probable, mais il est également possible que vous vous retrouviez avec des doublons. S'il existe deux requêtes consécutives pour insérer le même objet EmployeeTechnology dans le tableau, la validation de la deuxième requête peut se terminer (et réussir) avant que la première requête n'ait écrit dans la base de données. J'ai moi-même vu un scénario similaire avec une application sur laquelle j'ai travaillé. Même si l'application vérifiait l'unicité, si un utilisateur double-cliquait sur un bouton d'envoi, il y aurait des entrées en double dans la base de données. Dans ce cas, la désactivation du bouton au premier clic réduisait considérablement le risque. Ce petit risque peut être tolérable, selon vos besoins et l'impact d'avoir des entrées en double.

L'approche la plus logique dépend en grande partie de votre modèle d'accès et de vos besoins. J'espère que cela vous aidera.