mongodb - principales - ¿Posibilidad de que se genere Mongo ObjectId duplicado en dos colecciones diferentes?
objectid mongodb (4)
En caso de que alguien tenga problemas con los Object ID de Mongo duplicados, debe saber que, a pesar de la improbabilidad de que dups suceda en Mongo, es posible tener _id duplicados generados con PHP en Mongo.
El caso de uso en el que esto ha sucedido con regularidad es cuando estoy recorriendo un conjunto de datos y tratando de inyectar los datos en una colección.
La matriz que contiene los datos de inyección debe restablecerse explícitamente en cada iteración, incluso si no especifica el valor _id. Por alguna razón, el proceso INSERT agrega el _id de Mongo a la matriz como si fuera una variable global (incluso si la matriz no tiene alcance global). Esto puede afectarlo incluso si llama a la inserción en una llamada de función separada donde normalmente esperaría que los valores de la matriz no persistieran en la función de llamada.
Hay tres soluciones para esto:
- Puede
unset()
el campo _id de la matriz - Puede reiniciar toda la matriz con
array()
cada vez que recorre su conjunto de datos - Puede definir explícitamente el valor _id usted mismo (teniendo cuidado de definirlo de tal manera que no genere dups usted mismo).
Supongo que esto es un error en la interfaz de PHP, y no tanto un problema con Mongo, pero si se encuentra con este problema, simplemente deshaga el _id y debería estar bien.
¿Es posible generar exactamente el mismo Mongo ObjectId para un documento en dos colecciones diferentes? Me doy cuenta de que definitivamente es muy poco probable, pero ¿es posible?
Sin ser demasiado específico, la razón por la que pregunto es que con una aplicación en la que estoy trabajando, mostramos los perfiles públicos de los funcionarios electos que esperamos convertir en usuarios de pleno derecho de nuestro sitio. Tenemos colecciones separadas para los usuarios y los funcionarios electos que actualmente no son miembros de nuestro sitio. Hay varios otros documentos que contienen varios datos sobre los funcionarios electos que se relacionan con la persona que usa su ObjectId oficial elegido.
Después de crear la cuenta, seguimos resaltando los datos que están asociados al funcionario elegido, pero ahora también forman parte de la colección de usuarios con un ObjectId de usuarios correspondiente para asignar su perfil a las interacciones con nuestra aplicación.
Comenzamos a convertir nuestra aplicación de MySql a Mongo hace unos meses y, mientras estamos en transición, almacenamos la id. De MySql heredada para estos dos tipos de datos y también estamos empezando a almacenar ahora el Mongo ObjectId oficial elegido en los usuarios. documento para hacer un mapa de vuelta a los datos oficiales elegidos.
Estuve ponderando solo especificar el nuevo ObjectId del usuario como ObjectId oficial elegido anteriormente para simplificar las cosas, pero quería asegurarme de que no era posible tener una colisión con ningún ObjectId del usuario existente.
Gracias por tu visión.
Editar: Poco después de publicar esta pregunta, me di cuenta de que mi solución propuesta no era una muy buena idea. Sería mejor mantener el esquema actual que tenemos establecido y simplemente vincularlo con el ''_id'' oficial elegido en el documento del usuario.
Los ObjectIds se generan del lado del cliente de forma similar a UUID, pero con algunas propiedades más agradables para el almacenamiento en una base de datos, como el orden creciente y la codificación de su tiempo de creación de forma gratuita. La clave para su caso de uso es que están diseñados para garantizar la exclusividad a una alta probabilidad, incluso si se generan en diferentes máquinas.
Ahora, si se estuviera refiriendo al campo _id en general, no requerimos exclusividad en las colecciones, por lo que es seguro reutilizar el _id anterior. Como ejemplo concreto, si tiene dos colecciones, colors
y fruits
, ambos podrían tener simultáneamente un objeto como {_id: ''orange''}
.
En caso de que desee saber más acerca de cómo se crean ObjectIds, aquí está la especificación: http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-BSONObjectIDSpecification
No hay garantía alguna sobre la singularidad de ObjectId en las colecciones. Incluso si es probabilísticamente muy poco probable, sería un diseño de aplicación muy pobre que se basó en _id unicidad en todas las colecciones.
Uno puede probar esto fácilmente en el shell de 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" }
Por lo tanto, no confíe en que _id sea único en todas las colecciones, y como no controla la función de generación de ObjectID, no confíe en ella.
Es posible crear algo que se parezca más a un uuid, y si lo hace de forma manual, podría tener una mayor garantía de exclusividad.
Recuerde que puede poner objetos de diferentes "tipos" en la misma colección, entonces ¿por qué no simplemente poner sus dos "tablas" en la misma colección? Compartirían el mismo _id espacio, y por lo tanto, se garantizarían únicos. Cambiar de "prospectivo" a "registrado" sería un simple volteo de un campo ...
Respuesta corta
Solo para agregar una respuesta directa a su pregunta inicial: SÍ, si usa la generación de ID de objeto BSON, entonces para la mayoría de los controladores, las ID casi seguramente serán únicas en todas las colecciones. Vea a continuación qué significa "casi con certeza".
Respuesta larga
Es muy probable que los ID de objeto BSON generados por los controladores de Mongo DB sean únicos en todas las colecciones. Esto se debe principalmente a los últimos 3 bytes de la ID, que para la mayoría de los controladores se genera a través de un contador de incremento estático. Ese contador es independiente de la colección; es global. El controlador de Java, por ejemplo, usa un AtomicInteger estático, inicializado aleatoriamente.
Entonces, ¿por qué, en los documentos de Mongo, dicen que los ID son "altamente probables" para ser únicos, en lugar de decir directamente que SERÁN únicos? Pueden ocurrir tres posibilidades en las que no obtendrá una identificación única (por favor, avíseme si hay más):
Antes de esta discusión, recuerde que el ID de objeto BSON consiste en:
[4 bytes en bytes desde época, hash de máquina de 3 bytes, ID de proceso de 2 bytes, contador de 3 bytes]
Estas son las tres posibilidades, así que juzga por ti mismo qué tan probable es que te engañen:
1) Desbordamiento del contador: hay 3 bytes en el contador. Si inserta más de 16,777,216 (2 ^ 24) documentos en un solo segundo, en la misma máquina, en el mismo proceso, puede desbordar los bytes del contador de incremento y terminar con dos ID de objeto que comparten el mismo tiempo, la máquina , proceso y valores de contador.
2) Contador no incrementado: algunos controladores Mongo usan números aleatorios en lugar de incrementar los números para los bytes del contador. En estos casos, existe una posibilidad de 1 / 16,777,216 de generar una ID no única, pero solo si esas dos ID se generan en el mismo segundo (es decir, antes de la sección de tiempo de las actualizaciones de ID para el siguiente segundo), en el mismo máquina, en el mismo proceso.
3) Machine and process hash a los mismos valores. Los valores de ID de máquina e ID de proceso pueden, en un escenario altamente improbable, asociar los mismos valores para dos máquinas diferentes. Si esto ocurre, y al mismo tiempo los dos contadores en las dos máquinas diferentes, durante el mismo segundo, generan el mismo valor, entonces usted terminará con una identificación duplicada.
Estos son los tres escenarios a tener en cuenta. Los escenarios 1 y 3 parecen altamente improbables, y el escenario 2 es totalmente evitable si está utilizando el controlador correcto. Deberá verificar la fuente del controlador para estar seguro.