1. Visão geral
Às vezes, precisamos do ID de um documento que acabamos de inserir em um banco de dados MongoDB. Por exemplo, podemos querer enviar de volta o ID como resposta a um chamador ou registrar o objeto criado para depuração.
Neste tutorial, veremos como os IDs são implementados no MongoDB e como recuperar o ID de um documento que acabamos de inserir em uma coleção por meio de um programa Java.
2. Qual é o ID de um documento do MongoDB?
Como em todo sistema de armazenamento de dados, o MongoDB precisa de um identificador exclusivo para cada documento armazenado em uma coleção. Esse identificador é equivalente à chave primária em bancos de dados relacionais.
No MongoDB, esse ID é composto por 12 bytes:
- um valor de carimbo de data/hora de 4 bytes representa os segundos desde a época do Unix
- um valor aleatório de 5 bytes gerado uma vez por processo. Esse valor aleatório é exclusivo da máquina e do processo.
- um contador de incremento de 3 bytes
O ID é armazenado em um campo chamado _id e é gerado pelo cliente. Isso significa que o ID deve ser gerado antes de enviar o documento para o banco de dados. No lado do cliente, podemos usar um ID gerado pelo driver ou gerar um ID personalizado.
Podemos ver que documentos criados pelo mesmo cliente no mesmo segundo terão os primeiros 9 bytes em comum. Portanto, a exclusividade do ID depende do contador nesse caso. O contador permite que um cliente crie mais de 16 milhões de documentos no mesmo segundo.
Embora comece com um carimbo de data/hora, devemos ter cuidado para que o identificador não seja usado como critério de classificação. Isso ocorre porque os documentos criados no mesmo segundo não têm garantia de serem classificados por data de criação, pois não é garantido que o contador seja monotônico. Além disso, clientes diferentes podem ter relógios de sistema diferentes.
O driver Java usa um gerador de números aleatórios para o contador, que não é monótono. É por isso que não devemos usar o ID gerado pelo driver para classificar por data de criação.
3. O ObjectId Classe
O identificador exclusivo é armazenado em um ObjectId class que fornece métodos convenientes para obter os dados armazenados no ID sem analisá-los manualmente.
Por exemplo, veja como podemos obter a data de criação do ID:
Date creationDate = objectId.getDate();
Da mesma forma, podemos recuperar o timestamp do ID em segundos:
int timestamp = objectId.getTimestamp();
O ObjectId class também fornece métodos para obter o contador, o identificador de máquina ou o identificador de processo, mas todos estão obsoletos.
4. Recuperando o ID
A principal coisa a lembrar é que, no MongoDB, o cliente gera o identificador exclusivo de um Documento antes de enviá-lo para o cluster. Isso contrasta com as sequências em bancos de dados relacionais. Isso torna a recuperação desse ID bastante fácil.
4.1. ID gerado pelo driver
A maneira padrão e fácil de gerar o ID exclusivo de um Documento é deixar o motorista fazer o trabalho. Quando inserimos um novo Documento para uma Coleção , se não houver _id campo existe no Documento , o driver gera um novo ObjectId antes de enviar o comando insert para o cluster.
Nosso código para inserir um novo Documento em sua coleção pode ser assim:
Document document = new Document();
document.put("name", "Shubham");
document.put("company", "Baeldung");
collection.insertOne(document);
Podemos ver que nunca indicamos como o ID deve ser gerado.
Quando o insertOne() retorna, podemos obter o ObjectId gerado do Documento :
ObjectId objectId = document.getObjectId("_id");
Também podemos recuperar o ObjectId como um campo padrão do Documento e, em seguida, converta-o para ObjectId :
ObjectId oId = (ObjectId) document.get("_id");
4.2. ID personalizado
A outra maneira de recuperar o ID é gerá-lo em nosso código e colocá-lo no Documento como qualquer outro campo. Se enviarmos um Documento com um _id campo para o driver, ele não gerará um novo.
Podemos exigir isso em alguns casos em que precisamos do ID do Documento do MongoDB antes de inserir o Documento na Coleção .
Podemos gerar um novo ObjectId criando uma nova instância da classe:
ObjectId generatedId = new ObjectId();
Ou também podemos invocar o estático get() método do ObjectId aula:
ObjectId generatedId = ObjectId.get();
Em seguida, basta criar nosso Documento e use o ID gerado. Para isso, podemos fornecê-lo no Documento construtor:
Document document = new Document("_id", generatedId);
Alternativamente, podemos usar o put() método:
document.put("_id", generatedId);
Ao usar um ID gerado pelo usuário, devemos ter cuidado ao gerar um novo ObjectId antes de cada inserção, pois IDs duplicados são proibidos. IDs duplicados resultarão em uma MongoWriteException com uma mensagem de chave duplicada.
O ObjectId class fornece vários outros construtores que nos permitem definir algumas partes do identificador:
public ObjectId(final Date date)
public ObjectId(final Date date, final int counter)
public ObjectId(final int timestamp, final int counter)
public ObjectId(final String hexString)
public ObjectId(final byte[] bytes)
public ObjectId(final ByteBuffer buffer)
Mas devemos ter muito cuidado ao usar esses construtores, pois a exclusividade do ID fornecido ao driver depende inteiramente do nosso código. Podemos obter erros de chaves duplicadas nestes casos específicos:
- se usarmos a mesma data (ou carimbo de data/hora) e combinação de contador várias vezes
- Se usarmos a mesma String hexadecimal , byte matriz ou ByteBuffer várias vezes