Projetar Campos MongoDB

MongoDBBeginner
Pratique Agora

Introdução

Neste laboratório, você aprenderá como usar a projeção do MongoDB para controlar quais campos aparecem nos resultados de suas consultas. A projeção é um recurso poderoso que permite selecionar campos específicos para retornar, o que pode reduzir a quantidade de dados transferidos pela rede e melhorar o desempenho das consultas. Você praticará a inclusão e exclusão de campos, a projeção de campos dentro de documentos aninhados e o uso do framework de agregação para remodelar a saída. Ao final deste laboratório, você terá uma compreensão sólida de como usar efetivamente a projeção em suas consultas MongoDB.

Selecionar Campos Específicos com Projeção

Nesta primeira etapa, você aprenderá os conceitos básicos de projeção, selecionando apenas os campos específicos que deseja ver nos resultados de suas consultas. Isso é conhecido como projeção "inclusiva".

Primeiro, abra o MongoDB Shell. Esta interface interativa de linha de comando é onde você executará todos os seus comandos de banco de dados para este laboratório.

mongosh

Você está agora dentro do MongoDB Shell. O prompt do seu terminal mudará para indicar que você está conectado. Vamos mudar para um novo banco de dados chamado projectlab_database e inserir alguns dados de exemplo. Se o banco de dados não existir, o MongoDB o criará para você quando você armazenar dados pela primeira vez.

use projectlab_database

Em seguida, insira três documentos em uma coleção chamada users.

db.users.insertMany([
  {
    name: "John Doe",
    age: 30,
    email: "john.doe@example.com",
    city: "New York",
    job: "Software Engineer"
  },
  {
    name: "Jane Smith",
    age: 28,
    email: "jane.smith@example.com",
    city: "San Francisco",
    job: "Data Scientist"
  },
  {
    name: "Mike Johnson",
    age: 35,
    email: "mike.johnson@example.com",
    city: "Chicago",
    job: "Product Manager"
  }
]);

Agora, vamos consultar esta coleção. Para retornar apenas os campos name e age para todos os documentos, você adiciona um documento de projeção como o segundo argumento para o método find(). No documento de projeção, você especifica os campos a serem incluídos com um 1. Por padrão, o campo _id é sempre retornado. Você pode excluí-lo explicitamente definindo seu valor como 0.

db.users.find({}, { name: 1, age: 1, _id: 0 });

Você deverá ver a seguinte saída, que contém apenas os campos name e age para cada usuário:

[
  { "name": "John Doe", "age": 30 },
  { "name": "Jane Smith", "age": 28 },
  { "name": "Mike Johnson", "age": 35 }
]

Esta técnica é muito útil para recuperar apenas os dados necessários, o que é especialmente importante ao trabalhar com documentos grandes.

Excluir Campos Específicos dos Resultados

Além de selecionar quais campos incluir, você também pode especificar quais campos excluir. Isso é conhecido como projeção "exclusiva" e é útil quando você deseja ver a maioria dos campos, mas ocultar alguns, como os sensíveis ou grandes.

Você ainda deve estar no shell mongosh com o projectlab_database selecionado.

Para excluir campos, você define o valor deles como 0 no documento de projeção. Vamos executar uma consulta para buscar todos os dados do usuário, mas excluir os campos email e city.

db.users.find({}, { email: 0, city: 0 });

A saída incluirá todos os campos, exceto email e city. Observe que o campo _id ainda é incluído por padrão.

[
  {
    _id: ObjectId("..."),
    name: 'John Doe',
    age: 30,
    job: 'Software Engineer'
  },
  {
    _id: ObjectId("..."),
    name: 'Jane Smith',
    age: 28,
    job: 'Data Scientist'
  },
  {
    _id: ObjectId("..."),
    name: 'Mike Johnson',
    age: 35,
    job: 'Product Manager'
  }
]

Uma regra fundamental na projeção é que você não pode misturar inclusão (1) e exclusão (0) no mesmo documento de projeção. A única exceção a esta regra é o campo _id. Você pode excluir explicitamente o campo _id (_id: 0) mesmo ao incluir outros campos, como você fez na etapa anterior. Você também pode excluí-lo em uma projeção exclusiva.

Por exemplo, para excluir email, city e _id, você executaria o seguinte:

db.users.find({}, { email: 0, city: 0, _id: 0 });

Esta consulta retorna documentos contendo apenas os campos name, age e job.

Projetar Campos em Documentos Aninhados

Dados do mundo real são frequentemente estruturados com documentos e arrays aninhados. As capacidades de projeção do MongoDB permitem selecionar precisamente campos, mesmo quando eles estão embutidos profundamente na estrutura de um documento.

Primeiro, vamos limpar a coleção users existente e inserir novos documentos que tenham um objeto contact aninhado e um array skills.

db.users.deleteMany({});

Agora, insira os novos dados.

db.users.insertMany([
  {
    name: "John Doe",
    contact: {
      email: "john.doe@example.com",
      phone: {
        mobile: "123-456-7890",
        work: "987-654-3210"
      }
    },
    skills: ["JavaScript", "MongoDB", "React"]
  },
  {
    name: "Jane Smith",
    contact: {
      email: "jane.smith@example.com",
      phone: {
        mobile: "234-567-8901",
        work: "876-543-2109"
      }
    },
    skills: ["Python", "Data Science", "Machine Learning"]
  }
]);

Para projetar um campo dentro de um documento aninhado, você usa a "notação de ponto" (dot notation). Por exemplo, para selecionar o name do usuário e o número de telefone celular, você especificaria "contact.phone.mobile": 1. Vamos tentar projetar o name, email e o número de telefone celular.

db.users.find(
  {},
  {
    name: 1,
    "contact.email": 1,
    "contact.phone.mobile": 1,
    _id: 0
  }
);

O resultado preservará a estrutura aninhada para os campos selecionados:

[
  {
    "name": "John Doe",
    "contact": {
      "email": "john.doe@example.com",
      "phone": { "mobile": "123-456-7890" }
    }
  },
  {
    "name": "Jane Smith",
    "contact": {
      "email": "jane.smith@example.com",
      "phone": { "mobile": "234-567-8901" }
    }
  }
]

Você também pode projetar uma parte de um array usando o operador $slice. Para obter o name e apenas as duas primeiras habilidades de cada usuário, execute o seguinte comando:

db.users.find({}, { name: 1, skills: { $slice: 2 }, _id: 0 });

A saída mostrará cada usuário com um array skills contendo apenas dois elementos:

[
  { "name": "John Doe", "skills": ["JavaScript", "MongoDB"] },
  { "name": "Jane Smith", "skills": ["Python", "Data Science"] }
]

Remodelar Campos de Saída com Agregação

Para transformações mais avançadas, como renomear campos ou criar novos campos computados, a projeção do método find() não é suficiente. Em vez disso, você pode usar o framework de agregação, especificamente o estágio $project.

Vamos preparar nossos dados para esta etapa. Limpe a coleção e insira usuários com informações de salário.

db.users.deleteMany({});
db.users.insertMany([
  {
    name: "John Doe",
    age: 30,
    salary: 75000,
    department: "Engineering"
  },
  {
    name: "Jane Smith",
    age: 28,
    salary: 85000,
    department: "Data Science"
  },
  {
    name: "Mike Johnson",
    age: 35,
    salary: 95000,
    department: "Management"
  }
]);

O estágio $project em um pipeline de agregação pode remodelar documentos adicionando novos campos, renomeando campos existentes ou removendo campos. Para usá-lo, você passa um array de estágios para o método aggregate().

Para renomear um campo, você define um novo nome de campo e atribui a ele o valor de um campo existente, prefixado com um sinal de $. Vamos renomear name para fullName e age para yearsOld.

db.users.aggregate([
  {
    $project: {
      fullName: "$name",
      yearsOld: "$age",
      _id: 0
    }
  }
]);

Você também pode criar novos campos com base em cálculos. Vamos criar um campo monthlySalary dividindo o salary anual por 12, e um campo salaryTier com base em lógica condicional usando o operador $switch.

db.users.aggregate([
  {
    $project: {
      name: 1,
      monthlySalary: { $divide: ["$salary", 12] },
      salaryTier: {
        $switch: {
          branches: [
            { case: { $lt: ["$salary", 80000] }, then: "Junior" },
            { case: { $gte: ["$salary", 80000] }, then: "Senior" }
          ],
          default: "Unknown"
        }
      },
      _id: 0
    }
  }
]);

A saída será uma estrutura de documento completamente nova que você definiu no estágio $project:

[
  { "name": "John Doe", "monthlySalary": 6250, "salaryTier": "Junior" },
  {
    "name": "Jane Smith",
    "monthlySalary": 7083.333333333333,
    "salaryTier": "Senior"
  },
  {
    "name": "Mike Johnson",
    "monthlySalary": 7916.666666666667,
    "salaryTier": "Senior"
  }
]

O estágio $project oferece controle total sobre a forma final dos resultados da sua consulta, permitindo transformações de dados poderosas diretamente no banco de dados.

Resumo

Neste laboratório, você aprendeu a controlar efetivamente a saída das suas consultas MongoDB usando projeção. Você começou com os conceitos básicos de inclusão e exclusão de campos com o método find(). Em seguida, progrediu para tópicos mais avançados, como o uso da notação de ponto (dot notation) para projetar campos dentro de documentos aninhados e o uso do operador $slice para retornar um subconjunto de um array. Finalmente, você explorou o poder do estágio $project do framework de agregação para remodelar completamente documentos, renomeando campos, criando novos campos computados e aplicando lógica condicional. Essas habilidades são fundamentais para escrever consultas eficientes e precisas no MongoDB.