mongodb - update - objectid nodejs




Possibilité de dupliquer Mongo ObjectId généré dans deux collections différentes? (3)

Dans le cas où quelqu'un aurait des problèmes avec des ObjectIDs Mongo en double, sachez que malgré le peu de risques de dups dans Mongo lui-même, il est possible d'avoir des _id dupliqués générés avec PHP dans Mongo.

Le cas d'utilisation où cela s'est produit avec régularité pour moi est lorsque je parcourt un ensemble de données et que j'essaie d'injecter les données dans une collection.

Le tableau contenant les données d'injection doit être explicitement réinitialisé à chaque itération, même si vous ne spécifiez pas la valeur _id. Pour une raison quelconque, le processus INSERT ajoute le _id Mongo au tableau comme s'il s'agissait d'une variable globale (même si le tableau n'a pas de portée globale). Cela peut vous affecter même si vous appelez l'insertion dans un appel de fonction distinct où vous attendez normalement que les valeurs du tableau ne persistent pas dans la fonction appelante.

Il y a trois solutions à cela:

  1. Vous pouvez unset() le champ _id du tableau
  2. Vous pouvez réinitialiser le tableau entier avec array() chaque fois que vous bouclez votre ensemble de données
  3. Vous pouvez définir vous-même explicitement la valeur _id (en prenant soin de la définir de telle sorte que vous ne génériez pas vous-même de dups).

Ma conjecture est que c'est un bug dans l'interface PHP, et pas tellement un problème avec Mongo, mais si vous rencontrez ce problème, il suffit de désactiver le _id et vous devriez être bien.

Est-il possible que le même Mongo ObjectId exact soit généré pour un document dans deux collections différentes? Je réalise que c'est très improbable, mais est-ce possible?

Sans entrer dans les détails, la raison pour laquelle je pose la question est qu'avec une application sur laquelle je travaille, nous montrons des profils publics d'élus que nous espérons convertir en utilisateurs à part entière de notre site. Nous avons des collections séparées pour les utilisateurs et les élus qui ne sont pas actuellement membres de notre site. Il existe divers autres documents contenant divers éléments de données sur les représentants élus qui se réfèrent tous à la personne en utilisant leur ObjectID officiel élu.

Après avoir créé le compte, nous mettons toujours en évidence les données associées à l'élu, mais elles font également partie de la collection des utilisateurs avec un objet ObjectId correspondant pour mapper leur profil aux interactions avec notre application.

Nous avions commencé à convertir notre application de MySql à Mongo il y a quelques mois et pendant que nous sommes en transition, nous stockons l'identifiant MySql hérité pour ces deux types de données et nous commençons également à stocker l'objet Mongo ObjectId officiel dans les utilisateurs document pour reconstituer les données officielles élues.

Je réfléchissais simplement en spécifiant le nouvel utilisateur ObjectId en tant que ObjectId officiel élu précédent pour rendre les choses plus simples mais je voulais m'assurer qu'il n'était pas possible d'avoir une collision avec n'importe quel ObjectId utilisateur existant.

Merci pour votre perspicacité.

Edit: Peu de temps après avoir posté cette question, j'ai réalisé que ma solution proposée n'était pas une très bonne idée. Il vaudrait mieux garder simplement le schéma actuel que nous avons en place et simplement créer un lien vers l'élu officiel '_id' dans le document des utilisateurs.


Il n'y a aucune garantie sur l'unicité d'ObjectId entre les collections. Même si cela est très improbable, ce serait une très mauvaise conception d'application qui repose sur l'unicité de chaque collection.

On peut facilement tester ceci dans la coquille mongo:

MongoDB shell version: 1.6.5
connecting to: test
> db.foo.insert({_id: 'abc'})
> db.bar.insert({_id: 'abc'})
> db.foo.find({_id: 'abc'})
{ "_id" : "abc" }
> db.bar.find({_id: 'abc'})
{ "_id" : "abc" }
> db.foo.insert({_id: 'abc', data:'xyz'})
E11000 duplicate key error index: test.foo.$_id_  dup key: { : "abc" }

Donc, ne comptez absolument pas sur le fait que _id est unique à travers les collections, et puisque vous ne contrôlez pas la fonction de génération ObjectId, ne vous y fiez pas.

Il est possible de créer quelque chose qui ressemble plus à un uuid, et si vous le faites manuellement, vous pourriez avoir une meilleure garantie d'unicité.

Rappelez-vous que vous pouvez placer des objets de différents "types" dans la même collection, alors pourquoi ne pas simplement mettre vos deux "tables" dans la même collection. Ils partageraient le même espace, et ainsi, seraient garantis uniques. Passer de "prospectif" à "enregistré" serait un simple retournement d'un champ ...


Réponse courte

Juste pour ajouter une réponse directe à votre question initiale: OUI, si vous utilisez la génération d'ID objet BSON, alors pour la plupart des pilotes, les ID seront presque certainement uniques dans les collections. Voir ci-dessous pour ce que signifie "presque certainement".

Longue réponse

Les ID d'objet BSON générés par les pilotes de base de données Mongo sont très susceptibles d'être uniques dans les collections. Cela est principalement dû aux 3 derniers octets de l'ID, qui pour la plupart des pilotes sont générés via un compteur d'incrémentation statique. Ce compteur est indépendant de la collection; c'est global. Le pilote Java, par exemple, utilise un AtomicInteger statique initialisé de manière aléatoire.

Alors pourquoi, dans les docs de Mongo, disent-ils que les identifiants sont "hautement probables" pour être uniques, au lieu de dire carrément qu'ils seront uniques? Trois possibilités peuvent se présenter lorsque vous ne recevrez pas d'identifiant unique (merci de me le signaler s'il y en a plus):

Avant cette discussion, rappelez-vous que l'ID d'objet BSON comprend:

[4 octets secondes depuis l'époque, hash machine 3 octets, ID processus 2 octets, compteur 3 octets]

Voici les trois possibilités, donc vous jugez par vous-même de la probabilité d'obtenir une dupe:

1) Dépassement de compteur: il y a 3 octets dans le compteur. Si vous insérez plus de 16 777 216 (2 ^ 24) documents en une seule seconde, sur la même machine, dans le même processus, vous pouvez déborder les octets du compteur incrémenté et vous retrouver avec deux ID d'objet partageant le même temps, la machine , processus et valeurs de compteur.

2) Compteur non incrémentant: certains pilotes Mongo utilisent des nombres aléatoires au lieu d'incrémenter des nombres pour les octets de compteur. Dans ces cas, il y a 1 / 16,777,216 chance de générer un ID non unique, mais seulement si ces deux ID sont générés dans la même seconde (c'est-à-dire avant que la section temporelle de l'ID ne passe à la seconde suivante). machine, dans le même processus.

3) Hacher la machine et traiter les mêmes valeurs. Les valeurs ID machine et ID de processus peuvent, dans un scénario hautement improbable, correspondre aux mêmes valeurs pour deux machines différentes. Si cela se produit, et en même temps, les deux compteurs sur les deux machines différentes, pendant la même seconde, génèrent la même valeur, alors vous vous retrouverez avec un ID dupliqué.

Ce sont les trois scénarios à surveiller. Les scénarios 1 et 3 semblent très peu probables, et le scénario 2 est totalement évitable si vous utilisez le bon pilote. Vous devrez vérifier la source du conducteur pour savoir à coup sûr.





nosql