Menu Docs

Página inicial do DocsDesenvolver aplicaçõesManual do MongoDB

Nomes de campo com pontos (.) e cifrões ($)

Nesta página

  • Visão geral
  • Inserir operações
  • Atualizações que substituem documentos
  • Atualizações que modificam documentos
  • Atualizações que usam aggregation pipelines
  • Restrições gerais

O MongoDB 5.0 adiciona suporte aprimorado para nomes de campo que são prefixados em dólar ($) ou que contêm períodos (.). As regras de validação para armazenar dados foram atualizadas para facilitar o trabalho com fontes de dados que usam esses caracteres.

Na maioria dos casos, os dados que foram armazenados utilizando nomes de campo como estes não são diretamente acessíveis. Você precisa utilizar métodos de auxiliar como $getField, $setField e $literal em consultas que acessam estes campos.

As regras de validação de nome de campo não são as mesmas para todos os tipos de operações de armazenamento. Esta página resume como diferentes operações de inserção e atualização lidam com nomes de campos prefixados em dólares ($).

Campos prefixados em dólar ($) são permitidos como nomes de campo de nível superior e aninhados para inserções.

db.sales.insertOne( {
"$price": 50.00,
"quantity": 30
} )

Campos prefixados em dólar ($) são permitidos em inserções usando palavras que, de outra forma, estariam reservadas. Nomes de operadores como $inc podem ser usados como nomes de campos, assim como palavras como id, db e ref.

db.books.insertOne( {
"$id": "h1961-01",
"location": {
"$db": "novels",
"$ref": "2007042768",
"$inc": true
} } )

Uma atualização que cria um novo documento durante um upsert é tratada como insert em vez de update para a validação do nome do campo. Upserts podem aceitar campos prefixados em dólar ($). No entanto, os upserts são um caso especial e operações de atualização semelhantes podem causar um erro se a parte match da atualização selecionar um documento existente.

Esse exemplo de código tem upsert: true, então ele inserirá um novo documento se a collection ainda não contiver um documento que corresponda ao termo de query { "date": "2021-07-07" }. Se esse código de amostra corresponder a um documento existente, a atualização falhará porque $hotel é prefixado em dólar ($).

db.expenses.updateOne(
{ "date": "2021-07-07" },
{ $set: {
"phone": 25.17,
"$hotel": 320.10
} },
{ upsert: true }
)

Os operadores de atualização substituem os campos existentes por novos documentos ou modificam esses campos. Nos casos em que a atualização executar uma substituição, campos prefixados em dólar ($) não são permitidos como nomes de campo de nível superior.

Considere um documento como

{
"_id": "E123",
"address": {
"$number": 123,
"$street": "Elm Road"
},
"$rooms": {
"br": 2,
"bath": 1
}
}

Você poderia usar um operador de atualização que substitui um documento existente para modificar o campo address.$street, mas não poderia atualizar o campo $rooms dessa forma.

db.housing.updateOne(
{ "_id": "E123" },
{ $set: { "address.$street": "Elm Ave" } }
)

Use $setField como parte de um pipeline de agregação para atualizar campos prefixados de dólar de nível superior ($) como $rooms.

Quando uma atualização modifica, em vez de substituir, os campos de documento existentes, os campos prefixados em dólar ($) podem ser nomes de campo de nível superior. Os subcampos podem ser acessados diretamente, mas você precisa de um método auxiliar para acessar os campos de nível superior.

Dica

Veja também:

Considere uma coleção com documentos como este registro de inventário:

{
_id: ObjectId("610023ad7d58ecda39b8d161"),
"part": "AB305",
"$bin": 200,
"quantity": 100,
"pricing": { sale: true, "$discount": 60 }
}

O subcampo pricing.$discount pode ser consultado diretamente.

db.inventory.findAndModify( {
query: { "part": { $eq: "AB305" } },
update: { $inc: { "pricing.$discount": 10 } }
} )

Utilize $getField e $literal para acessar o valor do campo de nível superior $bin.

db.inventory.findAndModify( {
query: { $expr: {
$eq: [ { $getField: { $literal: "$bin" } }, 200 ]
} },
update: { $inc: { "quantity": 10 } }
} )

Use $setField, $getFielde $literal no estágio $replaceWith para modificar campos prefixados em dólar ($) em um pipeline de agregação.

Considere uma collection de registros escolares como:

{
"_id": 100001,
"$term": "fall",
"registered": true,
"grade": 4
}

Crie uma nova collection para o semestre da primavera usando um pipeline para atualizar o campo $term prefixado em dólar ($).

db.school.aggregate( [
{ $match: { "registered": true } },
{ $replaceWith: {
$setField: {
field: { $literal: "$term" },
input: "$$ROOT",
value: "spring"
} } },
{ $out: "spring2022" }
] )

Além das regras de validação de armazenamento acima, há algumas restrições gerais sobre o uso de nomes de campos prefixados em dólar ($). Esses campos não podem:

  • Ser indexado

  • Ser usado como parte de uma chave de fragmento

  • Ser validados usando $jsonSchema

  • Ser modificados com uma sequência de escape

  • Ser usado com criptografia em nível de campo

  • Ser usado como subcampo em um documento _id

Aviso

Perda de dados possível com assinaturas em dólares ($) e períodos (.)

Há uma pequena chance de perda de dados ao usar nomes de campo com prefixo de cifrão ($) ou nomes de campo que contenham pontos (.) se esses nomes de campo forem usados em conjunto com gravações não reconhecidas de (write concern w=0) em servidores mais antigos que o MongoDB 5.0.

Ao executar os comandos insert, update e findAndModify , os drivers compatíveis com o 5.0 removem restrições ao uso de documentos com nomes de campos que são prefixados em dólar ($) ou que contêm pontos (.). Esses nomes de campo geraram um erro do lado do cliente nas versões anteriores do driver.

As restrições são removidas independentemente da versão do servidor à qual o driver está conectado. Se um driver do 5.0 enviar um documento para um servidor mais antigo, o documento será rejeitado sem enviar um erro.

Aviso

Preocupações de importação e exportação com assinaturas de dólar ($) e períodos (.)

A partir do MongoDB 5.0, os nomes dos campos do documento podem ter prefixo de cifrão ($) e podem conter pontos (.). No entanto, mongoimport e mongoexport podem não funcionar como esperado em algumas situações com nomes de campo que fazem uso destes caracteres.

O JSON estendido v2 MongoDB não consegue diferenciar entre os wrappers de tipo e os campos que têm o mesmo nome dos wrappers de tipo. Não use formatos JSON estendidos em contextos onde as representações BSON correspondentes possam incluir chaves prefixadas com cifrões ($). O mecanismo DBRef é uma exceção a esta regra geral.

Também há restrições quanto ao uso mongoimport e mongoexport com pontos (.) em nomes de campos. Como os arquivos CSV usam o ponto (.) para representar hierarquias de dados, um ponto (.) em um nome de campo será interpretado incorretamente como um nível de aninhamento.

← Consultas distribuídas