Tipos de JSON
BSON é um formato de serialização binária usado para armazenar documentos e fazer chamadas de procedimento remoto no MongoDB. A especificação BSON está localizada em bsonspec.org.
Cada tipo de BSON tem identificadores de número inteiro e de string, conforme listado na tabela a seguir:
Tipo | Número | Alias | Notas |
---|---|---|---|
Double | 1 | "double" | |
String | 2 | "string" | |
Objeto | 3 | "objeto" | |
Array | 4 | "array" | |
Dados binários | 5 | "binData" | |
Indefinido | 6 | " indefinido " | Obsoleto. |
ObjectId | 7 | "objectId" | |
Boolean | 8 | "bool" | |
Data | 9 | "data" | |
Zero | 10 | "nulo" | |
Expressão regular | 11 | "regex" | |
DBPointer | 12 | "dbPointer" | Obsoleto. |
JavaScript | 13 | "javascript" | |
Símbolo | 14 | "símbolo" | Obsoleto. |
Inteiro de bits | 16 | "int" | |
Timestamp | 17 | " carimbo de data/hora " | |
Inteiro de 64 bits | 18 | "long" | |
Decimal128 | 19 | "decimal" | |
Min key | -1 | "minKey" | |
Tecla máxima | 127 | "maxKey" |
O operador
$type
suporta utilizar estes valores para fazer uma query de campos pelo seu tipo de BSON.$type
também suporta o codinomenumber
, que corresponde aos tipos de BSON inteiro, decimal, double e longo.O operador de aggregation
$type
retorna o tipo BSON de seu argumento.O operador de agregação
$isNumber
retornatrue
se seu argumento for um inteiro BSON, decimal, double ou longo.
Para determinar o tipo de um campo, consulte Verificação de tipo.
Se você converter BSON em JSON, consulte a referência de JSON estendido .
As seções a seguir descrevem considerações especiais para tipos específicos de BSON.
Dados binários
Um valor binário BSON binData
é uma array de bytes. Um valor binData
tem um subtipo que indica como interpretar os dados binários. A tabela a seguir mostra os subtipos:
Número | Descrição |
---|---|
0 | Subtipo binário genérico |
1 | Dados de Função |
2 | Binário (antigo) |
3 | UUID (antigo) |
4 | UUID |
5 | md5 |
6 | Valor BSON criptografado |
7 | Dados de série temporal compactados Novidades na versão 5.2. |
8 | Dados confidenciais, como uma chave ou segredo. O MongoDB não registra valores literais para dados binários com subtipo 8. Em vez disso, o MongoDB registra um valor de espaço reservado de |
9 | Dados vetoriais, que são arrays densamente compactadas de números do mesmo tipo. |
128 | Dados personalizados |
ObjectId
ObjectIds são pequenos, provavelmente únicos, rápidos de gerar e ordenados. Os valores ObjectId têm 12 bytes de comprimento, consistindo em:
Um carimbo de data/hora de bytes, representando a criação do ObjectID, medido em segundos desde a época do Unix.
Um valor aleatório de 5bytes gerado uma vez por processo do lado do cliente . Este valor aleatório é exclusivo da máquina e do processo. Se o processo for reiniciado ou o nó primário do processo for alterado, este valor será gerado novamente.
Um contador incrementador de 3bytes por processo do lado do cliente , inicializado para um valor aleatório. O contador é redefinido quando um processo é reiniciado.
Para valores de carimbo de data/hora e contador, os bytes mais significativos aparecem primeiro na sequência de bytes (big-endian). Isto é diferente de outros valores de BSON, onde os bytes menos significativos aparecem primeiro (little-endian).
Se um valor inteiro for usado para criar um ObjectId, o número inteiro substituirá o carimbo de data/hora.
No MongoDB, cada documento armazenado em uma collection padrão requer um campo _id exclusivo que atua como uma chave primária. Se um documento inserido omitir o _id
campo, o driver MongoDB gerará automaticamente um ObjectID para o _id
campo.
Isso também se aplica a documentos inseridos por meio de operações de atualização com upsert: true.
Os clientes do MongoDB devem adicionar um campo _id
com um ObjectId único. A utilização de ObjectIds para o campo _id
fornece os seguintes benefícios adicionais:
Você pode acessar o tempo de criação de
ObjectId
emmongosh
usando o métodoObjectId.getTimestamp()
.Os ObjectIDs são aproximadamente ordenados por hora de criação, mas não estão perfeitamente ordenados. Classificar uma coleção em um campo
_id
contendo valoresObjectId
é aproximadamente equivalente a classificar por hora de criação.Importante
Embora os valores de ObjectId devam aumentar com o tempo, eles não são necessariamente monotônicos. Isso ocorre porque eles:
Contêm apenas um segundo de resolução temporal, portanto, os valores de ObjectId criados no mesmo segundo não têm uma ordenação garantida, e
São gerados por clientes, que podem ter relógios de sistema diferentes.
Utilize os métodos ObjectId()
para configurar e recuperar valores ObjectId.
A partir do MongoDB 5.0, mongosh
substitui o shell legado mongo
. Os métodos ObjectId()
funcionam de maneira diferente em mongosh
e no shell mongo
herdado. Para obter mais informações sobre os métodos legados, consulte Legacy mongo Shell.
String
As strings JSON são UTF-8. Em geral, os drivers para cada linguagem de programação convertem do formato de cadeia de caracteres da linguagem para UTF-8 ao serializar e desserializar BSON. Isso torna possível armazenar a maioria dos caracteres internacionais em strings BSON com facilidade. [1] Além disso, as $regex
queries do MongoDB suportam UTF-8 na string regex.
[1] | Dadas strings usando conjuntos de caracteres UTF-8, usar sort() em strings será razoavelmente correto. No entanto, como internamente sort() usa a api de strcmp C++, a ordem de classificação pode manipular alguns caracteres incorretamente. |
Carimbos de data e hora
O BSON tem um tipo especial de carimbo de data/hora para uso interno do MongoDB e não está associado ao tipo normal de Data. Esse tipo de carimbo de data/hora interno é um valor de 64 bits em que:
os 32 bits mais significativos são um valor de
time_t
(segundos desde a época Unix)os 32 bits menos significativos são um
ordinal
incremental para operações dentro de um determinado segundo.
Enquanto o formato BSON é little-endian e, portanto, armazena os bits menos significativos primeiro, a instância mongod
sempre compara o valor time_t
antes do valor ordinal
em todas as plataformas, independentemente da endianidade.
Na replicação, o oplog tem um campo ts
. Os valores neste campo refletem o tempo de operação, que utiliza um valor de carimbo de data/hora BSON.
Dentro de uma única instância mongod
, os valores de timestamp no oplog são sempre únicos.
Observação
O tipo de carimbo de data/hora BSON é para uso interno do MongoDB. Na maioria dos casos, no desenvolvimento de aplicativos, você desejará usar o tipo de data BSON. Consulte Data para obter mais informações.
Data
Data de JSON é um número inteiro de 1 bits que representa o número de milissegundos desde a época do Unix (1 de janeiro de 1970). Isso resulta em um período representável de cerca de 290 milhões de anos no passado e no futuro.
A especificação oficial da BSON refere-se ao tipo BSON Date como data e hora UTC.
O tipo de data BSON está assinado. [2] Valores negativos representam datas anteriores a 1970.
Para construir um Date
no mongosh
, você pode utilizar o construtor new Date()
ou ISODate()
.
Construir uma data com o novo construtor de data()
Para construir um Date
com o construtor new Date()
, execute o seguinte comando:
var mydate1 = new Date()
A variável mydate1
gera uma data e hora agrupadas como um ISODate:
mydate1
ISODate("2020-05-11T20:14:14.796Z")
Construa uma data com o construtor ISODate()
Para construir um Date
utilizando o construtor ISODate()
, execute o seguinte comando:
var mydate2 = ISODate()
A variável mydate2
armazena uma data e hora agrupadas como um ISODate:
mydate2
ISODate("2020-05-11T20:14:14.796Z")
Converter uma data em uma string
Para imprimir o Date
em um formato string
, use o método toString()
:
mydate1.toString()
Mon May 11 2020 13:14:14 GMT-0700 (Pacific Daylight Time)
Retornar a parte do mês de uma data
Você também pode retornar a parte do mês do valor Date
. Os meses são indexados a zero, de modo que janeiro é o mês 0
.
mydate1.getMonth()
4
[2] | Antes da versão 2.0, os valores Date eram interpretados incorretamente como números inteiros sem sinal, o que afetava as classificações, as queries de intervalo e os índices nos campos Date . Como os índices não são recriados durante a atualização, reindexe se tiver criado um índice sobre os valores Date com uma versão anterior e se as datas anteriores a 1970 forem relevantes para o seu aplicativo. |
decimal128
Tipo de dados JSON
decimal128
é uma 128representação decimal de bits para armazenar números muito grandes ou muito precisos, sempre que o arredondamento decimais for importante. Foi criado em de agosto 2009 como parte da revisão IEEE 754-2008 de pontos flutuantes. Quando você precisar de alta precisão ao trabalhar com tipos de dados BSON, deverá decimal128
usar.
decimal128
suporta 34 casas decimais de precisão ou significando junto com um intervalo de expoentes de -6143 a6144 +. O significando não é normalizado no decimal128
padrão, permitindo várias representações possíveis: 10 x 10^-1 = 1 x 10^0 = .1 x 10^1 = .01 x 10^2
etc. Ter a capacidade de armazenar valores máximos e mínimos na ordem de 10^6144
10^-6143
e, respectivamente, permite um muita precisão.
Use decimal128
com o construtor NumberDecimal()
No MongoDB, você pode armazenar dados no formato decimal128
utilizando o construtor NumberDecimal()
. Se você passar o valor decimal como uma string, o MongoDB armazenará o valor no banco de dados da seguinte maneira:
NumberDecimal("9823.1297")
Você também pode passar o valor decimal como double
:
NumberDecimal(1234.99999999999)
Você também deve considerar o uso e o suporte que sua linguagem de programação tem para decimal128
. Os idiomas a seguir não oferecem suporte nativo a esse recurso e exigem um plugin-in ou pacote adicional para obter a funcionalidade:
Python: O módulo decimal.Decimal pode ser usado para aritmética de ponto flutuante.
Java: a classe Java BigDecimal oferece suporte para
decimal128
números.Node.js: existem vários pacotes que oferecem suporte, como js-big-decimal ou node.js bigdecimal disponível no npm.
Casos de uso
Quando você realiza cálculos matemáticos programaticamente, às vezes, pode receber resultados inesperados. O exemplo a seguir em Node.js produz resultados incorretos:
> 0.1 0.1 > 0.2 0.2 > 0.1 * 0.2 0.020000000000000004 > 0.1 + 0.1 0.010000000000000002
Da mesma forma, o exemplo a seguir em Java produz uma saída incorreta:
1 class Main { 2 public static void main(String[] args) { 3 System.out.println("0.1 * 0.2:"); 4 System.out.println(0.1 * 0.2); 5 } 6 }
1 0.1 * 0.2: 2 0.020000000000000004
Os mesmos cálculos em Python, Ruby, Rust e outras linguagens produzem os mesmos resultados. Isso acontece porque os números binários de ponto flutuante não representam bem os valores base 10.
Por exemplo, o 0.1
utilizado nos exemplos acima é representado em binário como 0.0001100110011001101
. Na maioria das vezes, isso não causa problemas significativos. No entanto, em aplicativos como financeiros ou bancos, em que a precisão é importante, use decimal128
como seu tipo de dados.