¿Es posible que se genere el mismo ObjectId Mongo exacto 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 perfiles públicos de funcionarios electos que esperamos convertir en usuarios completos 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 todos corresponden a la persona que usa su ObjectId oficial elegido.
Después de crear la cuenta, aún resaltamos los datos asociados al funcionario electo, pero ahora también forman parte de la colección de usuarios con un ObjectId de usuario correspondiente para asignar su perfil a las interacciones con nuestra aplicación.
Habíamos comenzado a convertir nuestra aplicación de MySql a Mongo hace unos meses y, mientras estamos en transición, almacenamos la identificación de MySql heredada para ambos tipos de datos y ahora también comenzamos a almacenar el ObjectId oficial de Mongo elegido en los usuarios. documento para asignar de nuevo a los datos oficiales elegidos.
Estaba pensando en especificar el nuevo ObjectId de usuario como el ObjectId oficial elegido anteriormente para simplificar las cosas, pero quería asegurarme de que no fuera posible tener una colisión con ningún ObjectId de usuario existente.
Gracias por tu perspicacia.
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 simplemente mantener el esquema actual que tenemos en su lugar y simplemente vincular al '_id' oficial elegido en el documento de los usuarios.
Respuestas:
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 seguramente serán únicas en todas las colecciones. Vea a continuación lo que significa "casi seguro".
Respuesta larga
Es muy probable que las ID de objeto BSON generadas por los controladores de Mongo DB sean únicas 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 Java, por ejemplo, utiliza un AtomicInteger estático inicializado aleatoriamente.
Entonces, ¿por qué, en los documentos de Mongo, dicen que las identificaciones son "altamente probables" para ser únicas, en lugar de decir que SERÁN únicas? Pueden ocurrir tres posibilidades en las que no obtendrá una identificación única (avíseme si hay más):
Antes de esta discusión, recuerde que el ID de objeto BSON consiste en:
[4 bytes segundos desde la época, hash de máquina de 3 bytes, ID de proceso de 2 bytes, contador de 3 bytes]
Estas son las tres posibilidades, para que juzgues por ti mismo la probabilidad de 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 de contador incrementales y terminar con dos ID de objeto que comparten el mismo tiempo, máquina , proceso y valores de contador.
2) Contador sin incremento: algunos controladores Mongo usan números aleatorios en lugar de números incrementales 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 que la sección de tiempo de la ID se actualice al siguiente segundo), en el mismo máquina, en el mismo proceso.
3) Máquina y proceso hash a los mismos valores. Los valores de ID de máquina e ID de proceso pueden, en un escenario altamente improbable, correlacionarse con 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 terminará con una ID 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. Tendrá que verificar la fuente del controlador para saber con certeza.
fuente
ObjectId
que tenía antes, siempre que el hash de la máquina, la identificación del proceso y el contador resulten todos igualesLos ObjectIds se generan del lado del cliente de manera similar al UUID pero con algunas propiedades más agradables para el almacenamiento en una base de datos, como aumentar el orden y codificar su tiempo de creación de forma gratuita. La clave para su caso de uso es que están diseñados para garantizar la unicidad a una alta probabilidad, incluso si se generan en máquinas diferentes.
Ahora, si se refería al campo _id en general, no requerimos unicidad entre las colecciones, por lo que es seguro reutilizar el antiguo _id. Como ejemplo concreto, si tiene dos colecciones,
colors
yfruits
, ambas podrían tener simultáneamente un objeto como{_id: 'orange'}
.En caso de que quiera saber más sobre cómo se crean ObjectIds, aquí está la especificación: http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-BSONObjectIDSpecification
fuente
En caso de que alguien tenga problemas con los ObjectID de Mongo duplicados, debe saber que, a pesar de la improbabilidad de que ocurran dups en Mongo, es posible tener _id's duplicados generados con PHP en Mongo.
El caso de uso en el que esto ha sucedido con regularidad para mí es cuando estoy recorriendo un conjunto de datos e intentando 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 está especificando el valor _id. Por alguna razón, el proceso INSERT agrega Mongo _id a la matriz como si fuera una variable global (incluso si la matriz no tiene un alcance global). Esto puede afectarlo incluso si está llamando a la inserción en una llamada de función separada donde normalmente esperaría que los valores de la matriz no persistan de nuevo a la función de llamada.
Hay tres soluciones para esto:
unset()
el campo _id de la matrizarray()
cada vez que recorre su conjunto de datosSupongo que esto es un error en la interfaz de PHP, y no es tanto un problema con Mongo, pero si se encuentra con este problema, simplemente desarme el _id y debería estar bien.
fuente
No hay garantía alguna sobre la unicidad de ObjectId en las colecciones. Incluso si es probabilísticamente muy improbable, sería un diseño de aplicación muy pobre que se basara en _id unicidad en todas las colecciones.
Uno puede probar esto fácilmente en el shell mongo:
Por lo tanto, no confíe en que _id sea único en todas las colecciones, y dado que no controla la función de generación de ObjectId, no confíe en ella.
Es posible crear algo más parecido a un líquido, y si lo hace manualmente, podría tener una mejor garantía de singularidad.
Recuerde que puede colocar 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 espacio _id, y por lo tanto, se les garantizaría un espacio único. Cambiar de "prospectivo" a "registrado" sería un simple cambio de campo ...
fuente