MongoDB e os Bancos de Dados Não Relacionais (noSQL)
Instalação
Primeiramente, baixamos o MongoDB:
sudo apt update
sudo apt install -y mongodb
mongo --version
Depois, baixamos o MongoDB Compass na versão Community Edition Stable clicando aqui.
Configurando o MongoDB
Vamos criar na raiz o diretório /data/db e rodar o servidor com o comando a seguir:
mongod
Podemos criar diretórios em outros lugares e rodar o servidor neles, basta utilizar o comando abaixo:
mongod --dbpath /path/diretorio
Para nos conectarmos ao servidor, vamos utilizar (em outro terminal) o comando abaixo. A porta por padrão é 27017, mas devemos conferir no terminal em que está rodando o servidor.
mongo --host localhost:porta
Dessa forma, nos deparamos com o terminal de uso do Mongo BD, que suporta a linguagem BSON.
Criando Banco de Dados
Criamos o análogo ao esquema em SQL:
use nome_do_banco
Assim que o BD é criado, somos mandados para ele.
Criando Coleções
Criamos o análogo às tabelas em SQL:
db.createCollection("nome_da_colecao")
Nós nos referimos a coleção como nome_do_banco.nome_da_colecao .
Deletando Coleções
db.nome_da_colecao.drop()
Inserindo Documentos
// Tipos de dados
// Dados são sempre armazenados como objetos
{
string: "String of text",
inteiro: 405,
double: 3.565,
booleano: true,
array: [1, 2, 3],
objeto: {atr1: "atr1", atr2: "atr2"},
data: new Date("<YYYY-mm-dd>"),
id_objeto: <IdObjeto>,
sem_valor: null
}
/*
Outros Tipos de dados
---------------------
Timestamp
Binary data
Regular expressions
JS Code
*/
// Inserindo um objeto
db.students.insertOne({name: "Jack", major: "Biology", gpa: 3.5})
// Insreindo um objeto com id detreminado
db.students.insertOne({_id: 4, name: "John", major: "Biology", gpa: 3.2})
// Inserindo um objeto com um atributo a mais
db.students.insertOne({name: "Claire", major: "Marketing", gpa: 3.7, awards: ["Valedictorian", "Summa Cum Laude"]} )
// Inserindo mais de um objeto
db.students.insertMany([
{name: "Mike", major: "Computer Science", gpa: 2.7},
{name: "Andrea", major: "Math", gpa: 4.0, awards: ["Summa Cum Laude"]}
])
Buscando Documentos
// Obtendo todos os estudantes
db.students.find( {} )
// Obtendo todos os estudantes ignorando o id
db.students.find( {} , {_id: 0})
// Obtendo os primeiros 3 estudantes
db.stuents.find( {} ).limit(3)
// Obter todos os estudantes ordenados pelo nome
db.students.find( {} ).sort( {name: 1} )
// Obter todos os estudantes inversamente ordenados pelo gpa, e depois ordenados pelo nome
db.students.find( {} ).sort( {gpa: -1, name: 1} )
// Obter os estudantes graduados em Biologia
db.students.find( {major: "Biology"} )
// Obter os estudantes com nome Jack e graduação em Biologia
db.students.find( {name: "Jack", major: "Biology"} )
// Obter os estudantes com o objeto contato gujo número é 333-3333 e o email é student@school.edu
db.students.find( {contact: {phone: "333-3333", email: "student@school.edu"} } )
// Obter todos os estudantes com nome Jack ou graduação em Química
db.students.find( { $or: [ {name: "Jack"}, {major: "Chemistry"} ] } )
// Obter todos os estudantes com gpa maior do que 7.5
// $eq, $ne, $lt, $lte, $gt, $gte
db.students.find( {gpa: {$gt: 7.5} } )
// Obter os estudantes com o nome contido no array
// $in, $nin
db.students.find( {name: {$in: ["Kate", "Claire"]} } )
// Obter os estudantes que possuem o atributo awards
db.students.find( {awards: {$exists: true} } )
// Obter os estudantes cujo nome é uma string
// Lista de Tipos e $types - https://docs.mongodb.com/manual/reference/bson-types/
db.students.find({name: {$type: 2} })
// Obter os estudantes em que o documento de índice 0 no array Notas é igual a 90
db.students.find( {"grades.0": 90 } )
// Obter os estudantes que possuem no array Notas o elemento 80
db.students.find( {grades: {$elemMatch: 80 } } )
// Obter os estudantes que possuem no array Notas um elemento maior do que 80
db.students.find( {grades: {$elemMatch: { $gt: 80} } } )
// Obter os estudantes que possuem um array Notas de tamanho 4
db.students.find( {grades: {$size: 4 } } )
Atualizando Documentos
// Mesmos filtros da inserção
db.stuents.metodoAtualizar(filtro, atualização, opções)
// Atualizar um atributo do primeiro documento
db.students.updateOne(
{major: "Biology"},
{
$set:
{major: "Bio"}
}
)
// Atualizar um atributo de todos os documentos
db.students.updateMany(
{major: "Bio"},
{
$set:
{major: "Biology"}
}
)
// Atualizar todo o primeiro documento
db.students.replaceOne(
{major: "Bio"},
{name: "new name", major: "new major", gpa: 4.0}
)
// Atualizar todos os documentos por inteiro
db.students.replaceMany(
{major: "Bio"},
{name: "new name", major: "new major", gpa: 4.0}
)
Deletando Documentos
// Deletar todos os documentos do banco
db.students.deleteMany({})
// Deletar apenas o primeiro documento
db.students.deleteOne({major: "Biology"})
// Deletar os documentos
db.students.deleteMany({gpa: {$gte: 3.5}})
Ações em Massa
db.students.bulkWrite(
[
{ insertOne : // Inserindo um elemento
{
"document" :
{
name: "Andrew", major: "Architecture", gpa: 3.2
}
}
},
{ insertOne :
{
"document" :
{
name: "Terry", major: "Math", gpa: 3.8
}
}
},
{ updateOne : // Atualizando um elemento
{
filter : { name : "Terry" },
update : { $set : { gpa : 4.0 } }
}
},
{ deleteOne : // Deletando um elemento
{ filter : { name : "Kate"} }
},
{ replaceOne : // Substituindo um elemento
{
filter : { name : "Claire" },
replacement : { name: "Genny", major: "Counsling", gpa: 2.4 }
}
}
],
{ordered: true} // Indicando que as ações devem ser feitas na ordem. Por padrão: true
);
Indexando Texto
// Criando um index de Nomes e Descrições chamado "text"
db.stores.createIndex( { name: "text", description: "text" } )
// Buscando, através de "text", documentos com a substring "Coffee"
db.stores.find({ $text: {$search: "Coffee" } })
// Buscando, através de "text", documentos com pelo menos uma das substrings: "Java", "Hut", "Coffee"
db.stores.find({ $text: {$search: "Java Hut Coffee" } })
// Buscando, através de "text", documentos com pelo menos uma das substrings: "Java", "Hut", "Coffee". Além disso, os documentos são rankeados pela proximidade com a pesquisa "text" (o score é "pesquisa" + "Score")
db.stores.find(
{ $text: { $search: "Java Hut Coffee" } },
{ score: { $meta: "textScore" } }
)
Agregação
db.purchase_orders.insertMany(
[
{product: "toothbrush", total: 4.75, customer: "Mike"},
{product: "guitar", total: 199.99, customer: "Tom"},
{product: "milk", total: 11.33, customer: "Mike"},
{product: "pizza", total: 8.50, customer: "Karen"},
{product: "toothbrush", total: 4.75, customer: "Karen"},
{product: "pizza", total: 4.75, customer: "Dave"}
{product: "toothbrush", total: 4.75, customer: "Mike"},
]
)
// Contar quantos documentos possuem determinado atributo
db.purchase_orders.count({product: "toothbrush"})
// Listar os documentos sem valores repetidos de um certo atributo
db.purchase_orders.distinct("product")
// Agrupar os documentos por um atributo e somar os valores de outro atributo
db.purchase_orders.aggregate(
[
{$match: {} },
{$group: {_id: "$customer", total: { $sum: "$total"} } }
]
)
// Agrupar os documentos por um atributo, somar os valores de outro atributo e inversamente ordenar por ele
db.purchase_orders.aggregate(
[
{$match: {} },
{$group: {_id: "$product", total: { $sum: "$total"} } },
{$sort: {total: -1}}
]
)
// Filtrar uma coleção, e em seguida agrupar os documentos por um atributo e somar os valores de outro atributo
db.purchase_orders.aggregate(
[
{$match: {product: {$in: ["toothbrush", "pizza"]} } },
{$group: {_id: "$product", total: { $sum: "$total"} } },
]
)
Para consultar os outros operadores de agregação, segue a página (em inglês) clicando aqui.
Problemas e Soluções
Endereço já em uso
Podemos nos deparar, ao tentar rodar o servidor do Mongo, com o seguinte erro:
Failed to set up listener: SocketException: Address already in use
Como proceder ? Basta matarmos o processo com o comando abaixo e rodar novamente o servidor.
sudo killall -15 mongod