Com base nos requisitos do seu software, você pode priorizar flexibilidade, escalabilidade, desempenho ou velocidade. Por isso, desenvolvedores e empresas muitas vezes ficam confusos ao escolher um banco de dados para suas necessidades. Se você procura um banco de dados altamente flexível e escalável, capaz de agregar dados para análise de clientes, o MongoDB pode ser a escolha ideal para você!

Neste artigo, discutiremos a estrutura do banco de dados do MongoDB e como criar, monitorar e gerenciar seu banco de dados! Vamos começar.

Como é a estrutura de um banco de dados MongoDB?

O MongoDB é um banco de dados NoSQL sem schema. Isso significa que você não especifica uma estrutura para tabelas/bancos de dados como faz em bancos de dados SQL.

Você sabia que os bancos de dados NoSQL são, na verdade, mais rápidos do que os bancos de dados relacionais? Isso se deve a funcionalidades como indexação, fragmentação e dutos de agregação. O MongoDB também é conhecido por sua rápida execução de consultas. É por isso que ele é preferido por empresas como Google, Toyota e Forbes.

Abaixo, exploraremos algumas funcionalidades-chave do MongoDB.

Documentos

MongoDB tem um modelo de dados de documentos que armazena dados como documentos JSON. Os documentos mapeiam naturalmente para os objetos no código do aplicativo, facilitando o uso para os desenvolvedores.

Em uma tabela de banco de dados relacional, você deve adicionar uma coluna para adicionar um novo campo. Esse não é o caso dos campos em um documento JSON. Os campos em um documento JSON podem diferir de documento para documento, então eles não serão adicionados a cada registro no banco de dados.

Os documentos podem armazenar estruturas como arrays que podem ser aninhadas para expressar relacionamentos hierárquicos. Além disso, MongoDB converte documentos em um tipo JSON binário (BSON). Isso garante acesso mais rápido e maior suporte a vários tipos de dados como string, integer, número booleano e muito mais!

Replica sets

Quando você cria um novo banco de dados no MongoDB, o sistema cria automaticamente pelo menos mais 2 cópias de seus dados. Estas cópias são conhecidas como “réplicas”, e elas replicam continuamente os dados entre elas, garantindo uma melhor disponibilidade dos seus dados. Elas também oferecem proteção contra tempo parado durante uma falha do sistema ou manutenção planejada.

Coleções

Uma coleção é um grupo de documentos associados a um banco de dados, semelhantes a tabelas em bancos de dados relacionais.

As coleções, no entanto, são muito mais flexíveis. Em primeiro lugar, elas não dependem de um schema. Em segundo lugar, os documentos não precisam ser do mesmo tipo de dados!

Para ver uma lista das coleções que pertencem a um banco de dados, use o comando listCollections.

Pipelines de agregação

Você pode usar esta estrutura para agrupar vários operadores e expressões. É flexível porque permite a você processar, transformar e analisar dados de qualquer estrutura.

Por causa disso, o MongoDB permite fluxos rápidos de dados e funcionalidades entre 150 operadores e expressões. Ele também possui vários estágios, como o estágio União, que reúne de forma flexível os resultados de múltiplas coleções.

Índices

Você pode indexar qualquer campo em um documento MongoDB para aumentar sua eficiência e melhorar a velocidade da consulta. A indexação economiza tempo ao digitalizar o índice para limitar os documentos inspecionados.

Você pode usar várias estratégias de indexação, incluindo índices compostos em vários campos. Por exemplo, digamos que você tenha vários documentos contendo o primeiro e último nome do funcionário em campos separados. Se você quiser que o primeiro e último nome sejam devolvidos, você pode criar um índice que inclua tanto “Sobrenome” quanto “Primeiro nome”. Isso seria muito melhor do que ter um índice em “Sobrenome” e outro em “Primeiro nome”.

Você pode utilizar ferramentas como o Performance Advisor para entender melhor qual consulta pode se beneficiar dos índices.

Sharding

O Sharding distribui um único conjunto de dados por vários bancos de dados. Esse conjunto de dados pode então ser armazenado em múltiplas máquinas para aumentar a capacidade total de armazenamento de um sistema. Isso porque ele divide conjuntos de dados maiores em partes menores e os armazena em vários nodes de dados.

MongoDB fragmenta dados no nível de coleta, distribuindo documentos em uma coleção através dos fragmentos em um cluster. Isso assegura a escalabilidade, permitindo que a arquitetura lide com os maiores aplicativos.

Como criar um banco de dados MongoDB

Você precisará instalar primeiro o plano MongoDB adequado para o seu sistema operacional. Vá para a página ‘Download MongoDB Community Server‘. Das opções disponíveis, selecione a última “versão”, o formato “pacote” como arquivo zip e a “plataforma” como seu sistema operacional e clique em “Download”, conforme mostrado abaixo:

This image depicts the available options- Version, Platform, and Package while downloading MongoDB Community Server.
O processo de download do servidor da comunidade MongoDB (Fonte da imagem: MongoDB Community Server)

O processo é bastante simples, então você terá o MongoDB instalado em seu sistema em pouco tempo!

Após a conclusão da instalação, verifique abrindo o prompt de comando e digitando mongod -version. Se você não obter o resultado a seguir, em vez disso, verá uma série de erros e talvez seja necessário reinstalar.

This is a code snippet to check the MongoDB version after installation.
Verificando a versão MongoDB. (Fonte da imagem: configserverfirewall)

Usando o MongoDB Shell

Antes de começarmos, certifique-se:

  • Seu cliente tem a Transport Layer Security e está em sua lista de permissão de IP.
  • Você tem uma conta de usuário e senha no cluster MongoDB desejado.
  • Você instalou o MongoDB em seu dispositivo.

Passo 1: Acesse a Shell MongoDB

Inicie o servidor MongoDB seguindo as instruções específicas de cada sistema operacional. Para Windows, digite o seguinte comando. Para outros sistemas operacionais, consulte a documentação do MongoDB.

net start MongoDB

Isso deve dar o seguinte resultado:

This is a code snippet to initialize the MongoDB server
Executando o servidor MongoDB. (Fonte da imagem: c-sharpcorner)

O comando anterior inicializou o servidor MongoDB. Para executá-lo, teríamos que digitar mongo no prompt de comando.

This is a code snippet to run the MongoDB server.
Executando o shell MongoDB. (Fonte da imagem: bmc)

Ao contrário dos bancos de dados relacionais comuns, o MongoDB não possui um comando de criação de banco de dados.

Passo 2: Crie seu banco de dados

Ao contrário do SQL, MongoDB não tem um comando de criação de banco de dados. Ao invés disso, existe uma palavra-chave chamada use que muda para um banco de dados especificado. Se o banco de dados não existir, ele irá criar um novo banco de dados, caso contrário, ele irá conectar ao banco de dados existente.

Por exemplo, para iniciar um banco de dados chamado “Company”, digite:

use Company
This is a code snippet to create a database in MongoDB.
Criando banco de dados no MongoDB.

Você pode digitar db para confirmar o banco de dados que você acabou de criar em seu sistema.

Se você quiser verificar os bancos de dados existentes, digite show dbs e ele mostrará todos os bancos de dados do seu sistema:

This is a code snippet to view the existing databases in the system.
Visualização de bancos de dados em MongoDB.

Por padrão, a instalação do MongoDB cria os bancos de dados admin, config e local.

Você notou que o banco de dados que criamos não está sendo exibido? Isso ocorre porque ainda não salvamos nenhum valor no banco de dados! Discutiremos a inserção na seção de gerenciamento do banco de dados.

Usando o Atlas UI

Você também pode começar com o serviço de banco de dados da MongoDB, Atlas. Embora você precise pagar para acessar algumas funcionalidades do Atlas, a maioria das funcionalidades do banco de dados estão disponíveis gratuitamente. As funcionalidades gratuitas são mais do que suficientes para criar um banco de dados MongoDB.

Antes de começarmos, certifique-se:

  1. Seu IP está na lista de permissões.
  2. Você tem uma conta de usuário e senha no cluster MongoDB que você deseja usar.

Para criar um banco de dados MongoDB com a Atlas UI, abra uma janela do navegador e faça o login em https://cloud.mongodb.com. A partir da sua página de cluster, clique em Browse Collections. Caso não tenha bancos de dados no cluster, você pode criar seu banco de dados clicando no botão Add My Own Data.

O prompt irá pedir que você forneça um banco de dados e um nome de coleção. Uma vez que você os tenha nomeado, clique em Create e pronto! Agora você pode inserir novos documentos ou conectar-se ao banco de dados usando drivers.

Gerenciando seu banco de dados MongoDB

Nesta seção, veremos algumas maneiras interessantes de gerenciar efetivamente seu banco de dados MongoDB. Você pode fazer isso usando o MongoDB Compass ou através de coleções.

Usando coleções

Enquanto bancos de dados relacionais possuem tabelas bem definidas com tipos de dados e colunas especificados, o NoSQL possui coleções em vez de tabelas. Essas coleções não têm nenhuma estrutura e os documentos podem variar — você pode ter diferentes tipos de dados e campos sem precisar corresponder ao formato de outro documento na mesma coleção.

Para demonstrar, criaremos uma coleção chamada “Funcionário” e adicionaremos um documento a ela:

db.Employee.insert(
  {
   	"Employeename" : "Chris",
   	"EmployeeDepartment" : "Sales"
  }
)

Caso a inserção seja bem-sucedida, ela retornará WriteResult({ "nInserted" : 1 }):

This code snippet returns WriteResult({
Inserção bem-sucedida no MongoDB.

Aqui, “db” se refere ao banco de dados atualmente conectado. “Employee” é a nova coleção criada no banco de dados da empresa.

Não definimos uma chave primária aqui porque o MongoDB cria automaticamente um campo chave-primário chamado “_id” e define um valor padrão para ele.

Execute o comando abaixo para verificar a coleção no formato JSON:

db.Employee.find().forEach(printjson)

Saída:

{
  "_id" : ObjectId("63151427a4dd187757d135b8"),
  "Employeename" : "Chris",
  "EmployeeDepartment" : "Sales"
}

Embora o valor “_id” seja atribuído automaticamente, você pode alterar o valor da chave primária padrão. Desta vez, vamos inserir outro documento no banco de dados “Employee”, com o valor “_id” como “1”:

db.Employee.insert(
  {  
   	"_id" : 1,
   	"EmployeeName" : "Ava",
   	"EmployeeDepartment" : "Public Relations"
  }
)

Ao executar o comando db.Employee.find().forEach(printjson) obtemos o seguinte resultado:

The output shows the documents in the Employee collection along with their primary key
Documentos na coleção com sua chave primária

Na saída acima, o valor “_id” para “Ava” é definido como “1″ ao invés de ser atribuído um valor automaticamente.

Agora que adicionamos valores ao banco de dados com sucesso, podemos verificar se ele aparece sob os bancos de dados existentes em nosso sistema usando o seguinte comando:

show dbs
The output shows the Employee collection in the existing databases in our system.
Exibindo a lista de bancos de dados

E pronto! Você criou com sucesso um banco de dados em seu sistema!

Usando o MongoDB Compass

Embora seja possível trabalhar com servidores MongoDB a partir do shell do Mongo, isso pode ser tedioso às vezes. Você pode experimentar isso em um ambiente de produção.

No entanto, há uma ferramenta chamada Compass (adequadamente nomeada) criada pela MongoDB que pode tornar tudo mais fácil. Ele tem uma interface gráfica de usuário melhor e funcionalidades adicionais como visualização de dados, perfis de desempenho e acesso CRUD (criar, ler, atualizar e excluir) a dados, bancos de dados e coleções.

Você pode baixar o Compass IDE para o seu sistema operacional e instalá-lo facilmente.

Em seguida, abra o aplicativo e crie uma conexão com o servidor, colando a string de conexão. Caso você não consiga encontrá-la, você pode clicar em Fill in connection fields individually. Se você não alterou o número da porta durante a instalação do MongoDB, basta clicar no botão connect, e você está pronto! Caso contrário, basta digitar os valores que você definiu e clicar em Connect.

This image shows the New Connection window, where you can choose to paste the connection url.
Nova janela de conexão em MongoDB. (Fonte da imagem: mongodb)

Em seguida, forneça o nome do host, a porta e a autenticação na janela New Connection.

No MongoDB Compass, você pode criar um banco de dados e adicionar sua primeira coleção simultaneamente:

  1. Clique em Create Database para abrir o prompt.
  2. Digite o nome do banco de dados e sua primeira coleção.
  3. Clique em Create Database.

Você pode inserir mais documentos no seu banco de dados clicando no nome do seu banco de dados, e depois clicando no nome da coleção para ver a aba Documents. Você pode então clicar no botão Add Data para inserir um ou mais documentos em sua coleção.

Ao adicionar seus documentos, você pode inseri-los um de cada vez ou como vários documentos em uma array. Se estiver adicionando vários documentos, certifique-se de que esses documentos separados por vírgula estejam dentro de colchetes. Por exemplo:

{ _id: 1, item: { name: "apple", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] },
{ _id: 2, item: { name: "banana", code: "123" }, qty: 20, tags: [ "B" ] },
{ _id: 3, item: { name: "spinach", code: "456" }, qty: 25, tags: [ "A", "B" ] },
{ _id: 4, item: { name: "lentils", code: "456" }, qty: 30, tags: [ "B", "A" ] },
{ _id: 5, item: { name: "pears", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] },
{ _id: 6, item: { name: "strawberry", code: "123" }, tags: [ "B" ] }

Finalmente, clique em Insert para adicionar os documentos à sua coleção. Este é o aspecto do corpo de um documento:

{
  "StudentID" : 1
  "StudentName" : "JohnDoe"
}

Aqui, os nomes dos campos são “StudentID” e “StudentName”. Os valores dos campos são “1” e “JohnDoe”, respectivamente.

Comandos úteis

Você pode gerenciar essas coleções por comandos de gerenciamento de funções e de gerenciamento de usuários.

Comandos de gerenciamento de usuários

Os comandos de gerenciamento de usuários do MongoDB contêm comandos que pertencem ao usuário. Podemos criar, atualizar e excluir os usuários usando estes comandos.

dropUser

Este comando remove um único usuário do banco de dados especificado. Abaixo está a sintaxe:

db.dropUser(username, writeConcern)

Aqui, o campo username é obrigatório e especifica o nome do usuário a ser removido do banco de dados. O campo opcional writeConcern contém o nível de preocupação com a escrita para a operação de remoção. O nível de Concern de escrita pode ser determinado pelo campo opcional writeConcern.

Antes de excluir um usuário que tenha a função userAdminAnyDatabase, certifique-se de que haja pelo menos outro usuário com privilégios de administração de usuários.

Neste exemplo, deixaremos o usuário “usuário26” no banco de dados de teste:

use test
db.dropUser("user26", {w: "majority", wtimeout: 4000})

Saída:

> db.dropUser("user26", {w: "majority", wtimeout: 4000});
true
createUser

Este comando cria um novo usuário para o banco de dados especificado como a seguir:

db.createUser(user, writeConcern)

Aqui, user é um campo obrigatório que contém o documento com autenticação e informações de acesso sobre o usuário a ser criado. O campo opcional writeConcern contém o nível de Concern de escrita para a operação de criação. O nível de Concern de escrita pode ser determinado pelo campo opcional, writeConcern.

createUser retornará um erro de usuário duplicado se o usuário já existir no banco de dados.

Você pode criar um novo usuário no banco de dados de teste da seguinte forma:

use test
db.createUser(
  {
    user: "user26",
    pwd: "myuser123",
    roles: [ "readWrite" ]  
  }
);

A saída é a seguinte:

Successfully added user: { "user" : "user26", "roles" : [ "readWrite", "dbAdmin" ] }
grantRolesToUser

Você pode usar este comando para conceder funções adicionais para um usuário. Para usá-lo, você precisa ter em mente a seguinte sintaxe:

db.runCommand(
  {
    grantRolesToUser: "<user>",
    roles: [ <roles> ],
    writeConcern: { <write concern> },
    comment: <any> 
  }
)

Você pode especificar tanto funções definidas pelo usuário quanto funções incorporadas nas funções mencionadas acima. Se você deseja especificar uma função que existe no mesmo banco de dados onde a função grantRolesToUser é executada, você pode especificar a função com um documento, conforme mencionado abaixo:

{ role: "<role>", db: "<database>" }

Ou, você pode simplesmente especificar a função com o nome da função. Por exemplo:

"readWrite"

Se você quiser especificar a função que está presente em um banco de dados diferente, você terá que especificar a função com um documento diferente.

Para conceder uma função em um banco de dados, você precisa da ação grantRole no banco de dados especificado.

Aqui está um exemplo para lhe dar uma imagem clara. Pegue, por exemplo, um produto do usuárioUser00 no banco de dados de produtos com as seguintes funções:

"roles" : [
  {
    "role" : "assetsWriter",
    "db" : "assets"
  }
]

A operação grantRolesToUser fornece ao “productUser00” a função readWrite no banco de dados de estoque e a função de leitura no banco de dados de produtos:

use products
db.runCommand({
  grantRolesToUser: "productUser00",
  roles: [
    { role: "readWrite", db: "stock"},
    "read"
  ],
  writeConcern: { w: "majority" , wtimeout: 2000 }
})

Agora, o usuário productUser00 no banco de dados de produtos possui as seguintes funções:

"roles" : [
  {
    "role" : "assetsWriter",
    "db" : "assets"
  },
  {
    "role" : "readWrite",
    "db" : "stock"
  },
  {
    "role" : "read",
    "db" : "products"
  }
]
usersInfo

Você pode usar o comando usersInfo para retornar informações sobre um ou mais usuários. Aqui está a sintaxe:

db.runCommand(
  {
    usersInfo: <various>,
    showCredentials: <Boolean>,
    showCustomData: <Boolean>,
    showPrivileges: <Boolean>,
    showAuthenticationRestrictions: <Boolean>,
    filter: <document>,
    comment: <any> 
  }
)
{ usersInfo: <various> }

Em termos de acesso, os usuários podem sempre olhar para suas próprias informações. Para olhar as informações de outro usuário, o usuário que executa o comando deve ter privilégios que incluem a ação viewUser no banco de dados do outro usuário.

Ao executar o comando userInfo, você pode obter as seguintes informações, dependendo das opções especificadas:

{
  "users" : [
    {
      "_id" : "<db>.<username>",
      "userId" : <UUID>, // Starting in MongoDB 4.0.9
      "user" : "<username>",
      "db" : "<db>",
      "mechanisms" : [ ... ],  // Starting in MongoDB 4.0
      "customData" : <document>,
      "roles" : [ ... ],
      "credentials": { ... }, // only if showCredentials: true
      "inheritedRoles" : [ ... ],  // only if showPrivileges: true or showAuthenticationRestrictions: true
      "inheritedPrivileges" : [ ... ], // only if showPrivileges: true or showAuthenticationRestrictions: true
      "inheritedAuthenticationRestrictions" : [ ] // only if showPrivileges: true or showAuthenticationRestrictions: true
      "authenticationRestrictions" : [ ... ] // only if showAuthenticationRestrictions: true
    },
  ],
  "ok" : 1
} 

Agora que você tem uma ideia geral do que é possível realizar com o comando usersInfo, a próxima pergunta que pode surgir é: quais comandos são úteis para visualizar usuários específicos e múltiplos usuários?

Aqui estão dois exemplos práticos para ilustrar o mesmo:
Para olhar os privilégios e informações específicas para usuários específicos, mas não as credenciais, para um usuário “Anthony” definido no banco de dados do “office”, execute o seguinte comando:

db.runCommand(
  {
    usersInfo:  { user: "Anthony", db: "office" },
    showPrivileges: true
  }
)

Se você quiser olhar para um usuário no banco de dados atual, você só pode mencionar o usuário pelo nome. Por exemplo, se você está no banco de dados home e um usuário chamado “Timothy” existe no banco de dados home, você pode executar o seguinte comando:

db.getSiblingDB("home").runCommand(
  {
    usersInfo:  "Timothy",
    showPrivileges: true
  }
)

A seguir, você pode usar um array se você desejar olhar as informações para vários usuários. Você pode incluir os campos opcionais showCredentials e showPrivileges, ou você pode optar por deixá-los de fora. Isso é o que o comando pareceria:

db.runCommand({
usersInfo: [ { user: "Anthony", db: "office" }, { user: "Timothy", db: "home" } ],
  showPrivileges: true
})
revokeRolesFromUser

Você pode aproveitar o comando revokeRolesFromUser para remover uma ou mais funções de um usuário no banco de dados onde as funções estão presentes. O comando revokeRolesFromUser tem a seguinte sintaxe:

db.runCommand(
  {
    revokeRolesFromUser: "<user>",
    roles: [
      { role: "<role>", db: "<database>" } | "<role>",
    ],
    writeConcern: { <write concern> },
    comment: <any> 
  }
)

Na sintaxe mencionada acima, você pode especificar tanto as funções definidas pelo usuário quanto as funções incorporadas no campo roles. Similar ao comando grantRolesToUser, você pode especificar a função que você deseja revogar em um documento ou usar seu nome.

Para executar com sucesso o comando revokeRolesFromUser, você precisa ter a ação revokeRole no banco de dados especificado.

Aqui está um exemplo para deixar isso mais claro. A entidade productUser00 no banco de dados “products” tinha as seguintes funções:

"roles" : [
  {
    "role" : "assetsWriter",
    "db" : "assets"
  },
  {
    "role" : "readWrite",
    "db" : "stock"
  },
  {
    "role" : "read",
    "db" : "products"
  }
]

O seguinte comando revokeRolesFromUser irá remover duas das funções do usuário: a função “read” de products e a função assetsWriter do banco de dados de “assets”:

use products
db.runCommand( { revokeRolesFromUser: "productUser00",
  roles: [
    { role: "AssetsWriter", db: "assets" },
    "read"
  ],
  writeConcern: { w: "majority" }
} )

O usuário “productUser00” no banco de dados de produtos agora tem apenas uma função restante:

"roles" : [
  {
    "role" : "readWrite",
    "db" : "stock"
  }
]

Comandos de gerenciamento de funções

As funções garantem aos usuários acesso aos recursos. Várias funções integradas podem ser usadas por administradores para controlar o acesso a um sistema MongoDB. Se as funções não cobrem os privilégios desejados, você pode criar novas funções em um banco de dados específico.

dropRole

Com o comando dropRole, você pode excluir uma função definida pelo usuário do banco de dados no qual você executa o comando. Para executar este comando, use a seguinte sintaxe:

db.runCommand(
  {
    dropRole: "<role>",
    writeConcern: { <write concern> },
    comment: <any> 
  }
)

Para uma execução bem-sucedida, você deve ter a ação dropRole no banco de dados especificado. As seguintes operações removeriam a função writeTags do banco de dados de “products”:

use products
db.runCommand(
  {
    dropRole: "writeTags",
    writeConcern: { w: "majority" }
  }
)
createRole

Você pode usar o comando createRole para criar uma função e especificar seus privilégios. Essa função será aplicada ao banco de dados no qual você escolher executar o comando. Caso a função já exista no banco de dados, o comando createRole retornará um erro de função duplicada.

Para executar este comando, siga a sintaxe:

db.adminCommand(
  {
    createRole: "<new role>",
    privileges: [
      { resource: { <resource> }, actions: [ "<action>", ... ] },
    ],
    roles: [
      { role: "<role>", db: "<database>" } | "<role>",
    ],
    authenticationRestrictions: [
      {
        clientSource: ["<IP>" | "<CIDR range>", ...],
        serverAddress: ["<IP>" | "<CIDR range>", ...]
      },
    ],
    writeConcern: <write concern document>,
    comment: <any> 
  }
)

Os privilégios de uma função se aplicariam ao banco de dados onde a função foi criada. A função pode herdar privilégios de outras funções em seu banco de dados. Por exemplo, uma função feita no banco de dados “admin” pode incluir privilégios que se aplicam ou a um cluster, ou a todos os bancos de dados. Ela também pode herdar privilégios de funções presentes em outros bancos de dados.

Para criar uma função em um banco de dados, você precisa ter duas coisas:

  1. A ação grantRole nesse banco de dados para mencionar privilégios para a nova função, assim como para mencionar funções a serem herdadas.
  2. A ação createRole no recurso do banco de dados.

O seguinte comando createRole irá criar uma função clusterAdmin no banco de dados do usuário:

db.adminCommand({ createRole: "clusterAdmin",
  privileges: [
    { resource: { cluster: true }, actions: [ "addShard" ] },
    { resource: { db: "config", collection: "" }, actions: [ "find", "remove" ] },
    { resource: { db: "users", collection: "usersCollection" }, actions: [ "update", "insert" ] },
    { resource: { db: "", collection: "" }, actions: [ "find" ] }
  ],
  roles: [
    { role: "read", db: "user" }
  ],
  writeConcern: { w: "majority" , wtimeout: 5000 }
})
grantRolesToRole

Com o comando grantRolesToRole, você pode conceder funções, uma função definida pelo usuário. O comando grantRolesToRole afetaria as funções no banco de dados onde o comando é executado.

Este comando grantRolesToRole tem a seguinte sintaxe:

db.runCommand(
  {
    grantRolesToRole: "<role>",
    roles: [
     { role: "<role>", db: "<database>" },
    ],
    writeConcern: { <write concern> },
    comment: <any> 
  }
)

Os privilégios de acesso são similares ao comando grantRolesToUser — você precisa de uma ação grantRole em um banco de dados para a execução correta do comando.

No exemplo a seguir, você pode usar o comando grantRolesToRole para atualizar a função productsReader no banco de dados “products” para herdar os privilégios da função productsWriter:

use products
db.runCommand(
  { 
    grantRolesToRole: "productsReader",
    roles: [
      "productsWriter"
    ],
    writeConcern: { w: "majority" , wtimeout: 5000 }
  }
)
revokePrivilegesFromRole

Você pode usar revokePrivilegesFromRole para remover os privilégios especificados da função definida pelo usuário no banco de dados onde o comando é executado. Para a execução correta, você precisa ter em mente a seguinte sintaxe:

db.runCommand(
  {
    revokePrivilegesFromRole: "<role>",
    privileges: [
      { resource: { <resource> }, actions: [ "<action>", ... ] },
    ],
    writeConcern: <write concern document>,
    comment: <any> 
  }
)

Para revogar um privilégio, o padrão “resource document” deve corresponder com o campo “resource” desse privilégio. O campo “actions” pode ser uma correspondência exata ou um subconjunto.

Por exemplo, considere a função manageRole no banco de dados de produtos com os seguintes privilégios que especificam o banco de dados de “managers” como o recurso:

{
  "resource" : {
    "db" : "managers",
    "collection" : ""
  },
  "actions" : [
    "insert",
    "remove"
  ]
}

Você não pode revogar as ações de “insert” ou “remove” de apenas uma coleção no banco de dados dos gerenciadores. As seguintes operações não causam nenhuma alteração na função:

use managers
db.runCommand(
  {
    revokePrivilegesFromRole: "manageRole",
    privileges: [
      {
        resource : {
          db : "managers",
          collection : "kiosks"
        },
        actions : [
          "insert",
          "remove"
        ]
      }
    ]
  }
)
db.runCommand(
  {
    revokePrivilegesFromRole: "manageRole",
    privileges:
      [
        {
          resource : {
          db : "managers",
          collection : "kiosks"
        },
        actions : [
          "insert"
        ]
      }
    ]
  }
)

Para revogar as ações de “insert” e/ou “remove” da função manageRole, você precisa corresponder exatamente ao documento do recurso. Por exemplo, a seguinte operação revoga apenas a ação “remove” do privilégio existente:

use managers
db.runCommand(
  {
    revokePrivilegesFromRole: "manageRole",
    privileges:
      [
        {
          resource : {
            db : "managers",
            collection : ""
        },
        actions : [ "remove" ]
      }
    ]
  }
)

A seguinte operação removerá múltiplos privilégios da função “executive” no banco de dados de gerenciadores:

use managers
db.runCommand(
  {
    revokePrivilegesFromRole: "executive",
    privileges: [
      {
        resource: { db: "managers", collection: "" },
        actions: [ "insert", "remove", "find" ]
      },
      {
        resource: { db: "managers", collection: "partners" },
        actions: [ "update" ]
      }
    ],
    writeConcern: { w: "majority" }
    }
)
rolesInfo

O comando rolesInfo retornará informações de privilégios e herança para funções específicas, incluindo funções integradas e definidas pelo usuário. Também é possível usar o comando rolesInfo para recuperar todas as funções que possuem escopo para um banco de dados.

Para uma execução adequada, siga esta sintaxe:

db.runCommand(
  {
    rolesInfo: { role: <name>, db: <db> },
    showPrivileges: <Boolean>,
    showBuiltinRoles: <Boolean>,
    comment: <any> 
  }
)

Para retornar informações para uma função do banco de dados atual, você pode especificar seu nome da seguinte forma:

{ rolesInfo: "<rolename>" }

Para retornar informações para uma função de outro banco de dados, você pode mencionar a função com um documento que menciona a função e o banco de dados:

{ rolesInfo: { role: "<rolename>", db: "<database>" } }

Por exemplo, o comando a seguir retorna as informações de herança de funções para o executivo da função definida no banco de dados de “managers”:

db.runCommand(
   {
      rolesInfo: { role: "executive", db: "managers" }
   }
)

Este próximo comando irá retornar as informações de herança de funções: accountManager no banco de dados no qual o comando é executado:

db.runCommand(
   {
      rolesInfo: "accountManager"
   }
)

O seguinte comando devolverá tanto os privilégios quanto a herança de funções para “executive”, conforme definido no banco de dados dos managers:

db.runCommand(
   {
     rolesInfo: { role: "executive", db: "managers" },
     showPrivileges: true
   }
)

Para mencionar várias funções, você pode usar um array. Você também pode mencionar cada função no array como uma string ou documento.

Você deve usar uma string somente se a função existir no banco de dados no qual o comando é executado:

{
  rolesInfo: [
    "<rolename>",
    { role: "<rolename>", db: "<database>" },
  ]
}

Por exemplo, o seguinte comando irá retornar informações para três funções em três bancos de dados diferentes:

db.runCommand(
   {
    rolesInfo: [
      { role: "executive", db: "managers" },
      { role: "accounts", db: "departments" },
      { role: "administrator", db: "products" }
    ]
  }
)

Você pode obter tanto os privilégios quanto a herança de funções da seguinte forma:

db.runCommand(
  {
    rolesInfo: [
      { role: "executive", db: "managers" },
      { role: "accounts", db: "departments" },
      { role: "administrator", db: "products" }
    ],
    showPrivileges: true
  }
)

Incorporando documentos MongoDB para um melhor desempenho

Bancos de dados de documentos, como o MongoDB, permitem que você defina seu schema de acordo com suas necessidades. Para criar schemas otimizados no MongoDB, é possível aninhar os documentos. Dessa forma, em vez de adaptar seu aplicativo a um modelo de dados, você pode construir um modelo de dados que corresponda ao seu caso de uso.

Documentos incorporados permitem que você armazene dados relacionados que são acessados juntos. Ao projetar schemas para MongoDB, é recomendado que você incorpore documentos por padrão. Use junções e referências do lado do banco de dados ou do aplicativo somente quando forem necessárias.

Certifique-se de que o carregamento de trabalho possa recuperar um documento com a frequência necessária. Ao mesmo tempo, o documento também deve ter todos os dados de que precisa. Isso é fundamental para o desempenho excepcional do seu aplicativo.

Abaixo, você encontrará alguns padrões diferentes para incorporar documentos:

Padrão de documento incorporado

Você pode usar isso para incorporar até mesmo sub-estruturas complicadas nos documentos com os quais eles são usados. Incorporar dados conectados em um único documento pode diminuir o número de operações de leitura necessárias para obter dados. Geralmente, você deve estruturar seu schema de forma que seu aplicativo receba todas as informações necessárias em uma única operação de leitura. Portanto, a regra é: o que é usado em conjunto deve ser armazenado em conjunto.

Padrão de subconjunto incorporado

O padrão do subconjunto incorporado é um caso híbrido. Você o usaria para uma coleção separada de uma longa lista de itens relacionados, onde alguns desses itens podem ser mantidos no documento principal para facilitar a exibição.

Aqui está um exemplo que lista as críticas de filmes:

> db.movie.findOne()
{   
  _id: 321475,   
  title: "The Dark Knight"
}  
> db.review.find({movie_id: 321475})
{   
  _id: 264579,   
  movie_id: 321475,   
  stars: 4   
  text: "Amazing"   
}
{   
  _id: 375684,   
  movie_id: 321475,   
  stars:5,   
  text: "Mindblowing"
}

Agora, imagine mil críticas semelhantes, mas você planeja exibir apenas as duas mais recentes quando você mostrar um filme. Neste cenário, faz sentido armazenar esse subconjunto como uma lista no documento do filme:

> db.movie.findOne({_id: 321475})   
{   
  _id: 321475,   
  title: "The Dark Knight",   
  recent_reviews: [   
    {_id: 264579, stars: 4, text: "Amazing"},   
    {_id: 375684, stars: 5, text: "Mindblowing"}   
  ]   
}</code

Em outras palavras, se você acessa rotineiramente um subconjunto de itens relacionados, certifique-se de incorporá-los.

Acesso independente

Armazenar subdocumentos em sua própria coleção pode ser uma boa ideia para separá-los da coleção principal.

Por exemplo, considere a linha de produtos de uma empresa. Se a empresa vende um pequeno conjunto de produtos, você pode querer armazená-los no documento da empresa. Mas se você quiser reutilizá-los em outras empresas ou acessá-los diretamente pelo seu número de identificação de estoque (SKU), também pode querer armazená-los em uma coleção separada.

Se você manipula ou acessa uma entidade independentemente, é uma boa prática armazená-la em uma coleção separada.

Listas ilimitadas

Armazenar listas curtas de informações relacionadas em um único documento pode ter uma desvantagem. Se a lista continuar crescendo sem controle, você não deveria colocá-la em um único documento. Isso ocorre porque você não conseguirá suportá-la por muito tempo.

Existem duas razões para isso. Primeiro, o MongoDB tem um limite no tamanho de um único documento. Segundo, se você acessar o documento com muita frequência, verá resultados negativos do uso de memória descontrolado.

Em resumo, se uma lista começar a crescer ilimitadamente, crie uma coleção para armazená-la separadamente.

Padrão de referência estendido

O padrão de referência estendido é como o padrão do subconjunto. Ele também otimiza as informações que você acessa regularmente para armazenar no documento.

Aqui, em vez de uma lista, ele é usado quando um documento se refere a outro que está presente na mesma coleção. Ao mesmo tempo, ele também armazena alguns campos desse outro documento para acesso rápido.

Por exemplo:

> db.movie.findOne({_id: 245434})
{   
  _id: 245434,   
  title: "Mission Impossible 4 - Ghost Protocol",   
  studio_id: 924935,   
  studio_name: "Paramount Pictures"   
}

Como você pode ver, “o studio_id” é armazenado para que você possa procurar mais informações sobre o estúdio que criou o filme. Mas o nome do estúdio também é copiado para este documento por simplicidade.

Para incorporar informações de documentos modificados regularmente, lembre-se de atualizar documentos onde você copiou essa informação quando ela for modificada. Em outras palavras, se você acessar rotineiramente alguns campos de um documento referenciado, incorpore-os.

Como monitorar o MongoDB

Você pode usar ferramentas de monitoramento como o Kinsta APM para depurar longas chamadas API, consultas lentas a bancos de dados, longas solicitações externas de URL, entre outras. Você também pode aproveitar comandos para melhorar o desempenho do banco de dados. Você também pode usá-los para inspecionar o saúde das instâncias do seu banco de dados.

Por que você deve monitorar os bancos de dados MongoDB?

Um aspecto chave do planejamento da administração do banco de dados é monitorar o desempenho e a saúde do seu cluster. O MongoDB Atlas lida com a maioria dos esforços de administração através de suas habilidades de tolerância a falhas/escala.

Apesar disso, os usuários precisam saber como rastrear os clusters. Eles também devem saber como escalar ou ajustar o que precisam antes de atingir uma crise.

Ao monitorar o banco de dados MongoDB, você pode:

  • Observar a utilização dos recursos.
  • Compreender a capacidade atual do seu banco de dados.
  • Detectar problemas em tempo real para aprimorar seus aplicativos.
  • Observar a presença de problemas de desempenho e comportamento anormal.
  • Alinhar-se com seus requisitos de governança/ proteção de dados e acordo de nível de serviço (SLA).

Principais métricas a serem monitoradas

Ao monitorar o MongoDB, existem quatro aspectos-chave que você precisa ter em mente:

Métricas de hardware do MongoDB

Aqui estão as principais métricas para monitorar o hardware:

CPU de processo normalizado

É definida como a porcentagem de tempo gasto pela CPU no software de aplicativo mantendo o processo do MongoDB.

Você pode escalar isso para um intervalo de 0-100% dividindo pelo número de núcleos de CPU. Isso inclui a CPU usada por módulos como kernel e usuário.

CPU de alto kernel pode mostrar exaustão da CPU através das operações do sistema operacional. Mas o usuário ligado às operações do MongoDB pode ser a causa raiz da exaustão da CPU.

CPU do sistema normalizado

É a porcentagem de tempo que a CPU gastou em chamadas de sistema, atendendo a este processo do MongoDB. Você pode dimensioná-la para uma faixa de 0-100% dividindo pelo número de núcleos de CPU. Também inclui a CPU usada por módulos como iowait, usuário, kernel, steal, etc.

A CPU do usuário ou o alto kernel pode mostrar exaustão da CPU através de operações MongoDB (software). Alto iowait pode estar ligado à exaustão do armazenamento causando a exaustão da CPU.

IOPS do disco

IOPS (Input/Output Operations Per Second) do disco é a média de operações de E/S (entrada/saída) consumidas por segundo na partição de disco do MongoDB.

Latência do disco

Esta é a latência do disco de leitura e gravação da partição em milissegundos em MongoDB. Valores altos (>500ms) mostram que a camada de armazenamento pode afetar o desempenho do MongoDB.

Memória do sistema

Use a memória do sistema para descrever os bytes de memória física usados vs o espaço livre disponível.

A métrica disponível aproxima o número de bytes de memória do sistema disponível. Você pode usá-lo para executar novas aplicações sem precisar usar a memória virtual.

Espaço em disco livre

Isso é definido como o total de bytes de espaço livre em disco na partição de disco do MongoDB. O MongoDB Atlas fornece capacidades escaláveis com base nessa métrica.

Uso de Swap

Você pode aproveitar um gráfico de uso de swap para descrever quanta memória está sendo colocada no dispositivo de swap. Uma alta métrica usada neste gráfico mostra que o swap está sendo utilizado. Isso mostra que a memória está sendo sub-provisionada para a carga de trabalho atual.

Métricas de conexão e operação do cluster do MongoDB

Aqui estão as principais métricas de operação e de conexão:

Tempos de execução de operação

O tempo médio de operação (operações de escrita e leitura) realizado durante o período de amostra selecionado.

Opcounters

É a taxa média de operações executadas por segundo durante o período de amostra selecionado. O gráfico/métrica de Opcounters mostra a distribuição de operações por tipo e velocidade para a instância.

Conexões

Esta métrica se refere ao número de conexões abertas para a instância. Picos ou números altos podem apontar para uma estratégia de conexão subótima tanto do lado do servidor não responsivo quanto do lado do cliente.

Query Targeting e Query Executors

Esta é a taxa média por segundo durante o período de amostra selecionada de documentos digitalizados. Para os executores de consultas, isso é durante a avaliação do plano de consultas e consultas. O objetivo da consulta mostra a relação entre o número de documentos escaneados e o número de documentos devolvidos.

Uma alta relação de número de pontos para operações subótimas. Estas operações digitalizam muitos documentos para devolver uma parte menor.

Digitalização e Encomenda

Ele descreve a taxa média por segundo ao longo do período de consultas escolhido. Ele retorna resultados ordenados que não podem executar a operação de ordenação usando um índice.

Filas

As filas podem descrever o número de operações à espera de um cadeado, seja para escrever ou para ler. Filas altas podem retratar a existência de menos do que um projeto de esquema ideal. Também pode indicar caminhos de escrita conflitantes, empurrando a alta competição sobre os recursos do banco de dados.

Métricas de replicação MongoDB

Aqui estão as principais métricas para o monitoramento da replicação:

Replication Oplog Window

Esta métrica lista o número aproximado de horas disponíveis no oplog de replicação do primário. Se um secundário ficar para trás mais do que essa quantidade, ele não conseguirá acompanhar e precisará de uma ressincronização completa.

Replication Lag

O atraso de replicação é definido como o número aproximado de segundos em que um nó secundário está atrasado em relação ao primário em operações de gravação. Um alto atraso de replicação indicaria que um secundário enfrenta dificuldades na replicação. Isso pode impactar a latência de suas operações, considerando a preocupação de leitura/gravação das conexões.

Replication Headroom

Essa métrica refere-se à diferença entre a janela do oplog de replicação primário e o atraso de replicação do secundário. Se esse valor for a zero, pode fazer com que um secundário entre no modo RECOVERING.

Opcounters – repl

Opcounters – repl é definido como a taxa média de operações de replicação executadas por segundo durante o período de amostra selecionado. Com a opcounters – gráfico/métrica, você pode dar uma olhada na velocidade das operações e na distribuição dos tipos de operações para a instância especificada.

Oplog GB/Hour

Isso é definido como a taxa média de gigabytes de oplog que o primário gera por hora. Altos volumes inesperados de oplog podem apontar para uma carga de trabalho de gravação altamente insuficiente ou um problema de design de esquema.

Ferramentas de monitoramento de desempenho MongoDB

O MongoDB possui ferramentas de interface do usuário integradas no Cloud Manager, Atlas e Ops Manager para rastreamento de desempenho. Ele também fornece alguns comandos e ferramentas independentes para visualizar dados mais baseados em dados brutos. Vamos falar sobre algumas ferramentas que você pode executar a partir de um host que tenha acesso e funções apropriadas para verificar seu ambiente:

mongotop

Você pode aproveitar este comando para rastrear que tempo uma instância do MongoDB gasta escrevendo e lendo dados por coleção. Use a seguinte sintaxe:

mongotop <options> <connection-string> <polling-interval in seconds>

rs.status()

Este comando retorna o status da réplica definida. Ele é executado do ponto de vista do membro onde o método é executado.

mongostat

Você pode usar o comando mongostat para obter uma visão rápida do status da sua instância do servidor MongoDB. Para uma saída ideal, você pode usá-lo para monitorar uma única instância para um evento específico, pois oferece uma visualização em tempo real.

Aproveite este comando para monitorar estatísticas básicas do servidor, como filas de bloqueio, distribuição de operações, estatísticas de memória do MongoDB e conexões/rede:

mongostat <options> <connection-string> <polling interval in seconds>

dbStats

Este comando retorna estatísticas de armazenamento para um banco de dados específico, tais como o número de índices e seu tamanho, dados totais de coleta vs tamanho de armazenamento e estatísticas relacionadas à coleta (número de coleções e documentos).

db.serverStatus()

Você pode aproveitar o comando db.serverStatus() para ter uma visão geral do estado do banco de dados. Ele lhe dá um documento representando os contadores de métricas da instância atual. Execute este comando em intervalos regulares para comparar estatísticas sobre a instância.

colStats

O comando collStats coleta estatísticas semelhantes às oferecidas pelo dbStats no nível de coleta. Sua saída consiste em uma contagem de objetos na coleção, a quantidade de espaço em disco consumida pela coleção, o tamanho da coleção e informações relativas a seus índices para uma determinada coleção.

Você pode usar todos esses comandos para oferecer relatórios e monitoramento em tempo real do servidor de banco de dados, permitindo que você monitore o desempenho e os erros do banco de dados e ajude na tomada de decisões informadas para refinar um banco de dados.

Como excluir um banco de dados MongoDB

Para excluir um banco de dados que você criou no MongoDB, você precisa se conectar a ele por meio da palavra-chave “use”.

Digamos que você criou um banco de dados chamado “Engineers”. Para se conectar ao banco de dados, você usará o seguinte comando:

use Engineers

Em seguida, digite db.dropDatabase() para excluir deste banco de dados. Após a execução, este é o resultado que você pode esperar:

{ "dropped"  :  "Engineers", "ok" : 1 }

Você pode executar o comando showdbs para verificar se o banco de dados ainda existe.

Resumo

Para extrair o máximo de valor do MongoDB, é fundamental ter uma compreensão sólida dos fundamentos. Por isso, é crucial conhecer os bancos de dados do MongoDB como a palma da sua mão. Isso requer familiarização com os métodos para criar um banco de dados primeiro.


Neste artigo, esclarecemos os diferentes métodos que você pode usar para criar um banco de dados no MongoDB, seguido por uma descrição detalhada de alguns comandos úteis do MongoDB para manter o controle dos seus bancos de dados. Finalmente, encerramos a discussão falando como você pode aproveitar documentos incorporados e ferramentas de monitoramento de desempenho no MongoDB para garantir que seu fluxo de trabalho funcione com eficiência máxima.

Qual é a sua opinião sobre esses comandos do MongoDB? Deixamos de fora algum aspecto ou método que você gostaria de ver aqui? Deixe-nos saber nos comentários!

Salman Ravoof

Salman Ravoof is a self-taught web developer, writer, creator, and a huge admirer of Free and Open Source Software (FOSS). Besides tech, he's excited by science, philosophy, photography, arts, cats, and food. Learn more about him on his website, and connect with Salman on Twitter.