03 MongoDB Flashcards
Modelos de Dados Agregados
(inexistente no modelo de dados relacionais)
(é preciso saber como e o que deseja-se saber)
(conhecimento da estrutura agregada ajuda a armazenar e distribuir os dados)
Trabalha-se com todos os dados reunidos
CRUD
Create
Read
Update
Delete
show dbs
mostra as databases instaladas
admin, config e local estâo automaticamente criados
use databaseX
switch or create and switch to databaseX
db.collectionX.insertOne( { Y } )
acrescenta na coleção collectionX (se a coleção não existe, é imediatamente criada), o documento (único) Y
Lembrar do parênteses e chaves
db.collectionX.insertOne( {
Y
} )
acrescenta na coleção collectionX (se a coleção não existe, é imediatamente criada), o documento (único) Y
Lembrar do parênteses e chaves
_id
Identificador aleatoriamente gerado, ou podemos definir se for do interesse
Não pode estar duplicado na mesma coleção ou database ?
db.collectionX.find( )
vs
db.collectionX.find( ).pretty( )
Tudo na mesma linha
Tudo arrumadinho
db.collectionX.deleteOne( {keyX: valueX} )
Deleta o primeiro documento com aquele valor naquela chave
db.collectionX.updateOne( { “filterX”: “valueX”}, { $set {“newLineX”: “valueY”} })
acrescenta newLineX: ValueY onde tem o value X na key filterX
db.collectionX.updateOne( { “filterX”: “valueX”}, { $set {“newLineX”: “valueY”} })
acrescenta newLineX: ValueY onde tem o value X na key filterX
db.collectionX.updateMany( { }, {markerX: “valueX”} )
adiciona o valueX a todos documentos da collectionX
db.collectionX.updateMany( { }, {markerX: “valueX”} )
adiciona ou substitue pelo valueX a todos documentos da collectionX
db.collectionX.insertMany ( [ { "key1": "valueX1" "key2": "valueX2" "key3": "valueX3" } { "key1": "valueY1" "key2": "valueY2" "key3": "valueY3" } ] )
Insere esses 2 documentos
db.collectionX.find( { filterX: “value Y”} )
tudo que tiver o valor “value Y” na chave “filter X” será retornado
db.collectionX.find( { numberX: {$gt: #Y} } )
numberX = qualquer chave cujos valores serão numéricos $gt (greater than), $lte (lower or equal than), etc #Y - valor numerico qualquer
db.collectionX.updateOne( {“key1”: “valueX1”}, {$set “key2”: “newValue2”} )
No primeiro documento com Key1=valueX1, muda o valor da key2 para newValue2
db.collectionX.update( {“key1”: “valueX1”}, {“key2”: “newValue2”} )
Onde tiver key1=valueX1 , deleta tudo e fica só “key2”: “newValue2”}
melhor usar updateOne e updateMany
db.collectionX.replaceOne( {“key1”: “valueX1”}, {“key2”: “newValue2”} )
substitui tudo no documento que tem key1=valueX1 por key2=newValue2 (poderiam ser várias linhas)
Objetivo final de projection:
Reduzir consumo de dados
db.collectionX.find ( { }, {keyX: 1, _id: 0} ).pretty()
Projection
Vai devolver todos os docs (filtro é { } ou seja, todos)
Mas só vai devolver a KeyX:ValueX de cada um (1 é sim). Não vai devolver a _id (0 é não, se não especificar devolve a _id por padrão). Não vai devolver nenhuma outra keyY, KeyZ etc porque o padrão destas é 0.
Embedded Documents = Nested documents
Documentos podem ter documentos dentro deles (total de 100 em hierarquia, portanto infinito) 100 levels of nesting
máximo 16mb/documento
db.collectionX.updateMany ( { }, {$set: {key1: {key2: “value2”, key3: “value3”, key4: {key5: “value5”, key6: “value6”}}}})
Adiciona a todos ( { } ) os objetos da collectionX, a key1 que contem a key2, key3 e key4, a key4 contem a key5 e key6.
Arrays = [ ]
List of Documents (tradução é matriz)
db.collectionX.updateOne ( {keyX= 666}, {$set: {keyY: [“bla”, “kkk”, “LOL”] } } )
no documento em que keyX=666, acrescenta na keyY uma array com as strings bla, kkk e LOL.
db.collectionX.findOne( {keyX: 99} ).keyY
Retorna o valueY do documento em que KeyX=99
db.collectionX.find ( {“keyX.keyY”: “valueY”} )
retorna os documentos cujo valor da keyY que está dentro da keyX, é valueY
MongoDB enforces no schemas! Documents don`t have to use the same schema inside of one collection!
But that does not mean that you can`t use some kind of schema!
But we probably prefer some kind of schema!
DATA TYPES
Text: " bla bla bla" Boolean: true or false Numbers: Integer(int32), NumberLong(int64), NumberDecimal (são os double, 2 números decimais) ObjectId (respects timestamps) ISODate("yyyy-mm-dd") Timestamp("garante que dois objetos criados ao mesmo tempo tem diferente timestamp") Embedded Document Arrays
new Date
new Timestamp
adiciona data atual
adiciona tempo atual
db.stats ( )
mostra espaço ocupado e diversas outras informações
typeof ( etc )
tipo do objeto
Important data type limits are:
Normal integers (int32) can hold a maximum value of +-2,147,483,647
Long integers (int64) can hold a maximum value of +-9,223,372,036,854,775,807
Text can be as long as you want - the limit is the 16mb restriction for the overall document
It’s also important to understand the difference between int32 (NumberInt), int64 (NumberLong) and a normal number as you can enter it in the shell. The same goes for a normal double and NumberDecimal.
NumberInt creates a int32 value => NumberInt(55)
NumberLong creates a int64 value => NumberLong(7489729384792)
If you just use a number (e.g. insertOne({a: 1}), this will get added as a normal double into the database. The reason for this is that the shell is based on JS which only knows float/ double values and doesn’t differ between integers and floats.
NumberDecimal creates a high-precision double value => NumberDecimal(“12.99”) => This can be helpful for cases where you need (many) exact decimal places for calculations.
When not working with the shell but a MongoDB driver for your app programming language (e.g. PHP, .NET, Node.js, …), you can use the driver to create these specific numbers.
Example for Node.js: http://mongodb.github.io/node-mongodb-native/3.1/api/Long.html
This will allow you to build a NumberLong value like this:
const Long = require(‘mongodb’).Long;
db.collection(‘wealth’).insert( {
value: Long.fromString(“121949898291”)
});
By browsing the API docs for the driver you’re using, you’ll be able to identify the methods for building int32s, int64s etc.
NESTED / EMBEDDED DOCUMENTS
Group data together logically
Great for data that belongs together and is not really overlapping with other data
Avoid super-deep nesting (100+lvls) or extremely long arrays (16mb size limit per document)
REFERENCES
Splita data across collections
Great for related but shared dat as well as for data which is used in relations and standalone
Allows you to overcome nesting and size limits (by creating new documents)
validationLevel
validationAction
which documents get validated?
strict = all inserts and updates
moderate = all inserts and updates to correct documents
what happens if validation fails?
erros = throw error and deny insert/update
warn = log warning but proceed
validationLevel
validationAction
which documents get validated?
strict = all inserts and updates
moderate = all inserts and updates to correct documents
what happens if validation fails?
erros = throw error and deny insert/update
warn = log warning but proceed
db.createCollection(“collectionX”, {validator: {$jasonSchema: {bla bla bla, bsonType: “ex: object”, required: [“keyX”, keyY”, “keyZ”], properties (exemplo: bsonType de cada objeto anterior, etc, comentário, descrição) } } } )
Exemplo do outro lado
db.createCollection(‘posts’, {
validator: {
$jsonSchema: {
bsonType: ‘object’,
required: [‘title’, ‘text’, ‘creator’, ‘comments’],
properties: {
title: {
bsonType: ‘string’,
description: ‘must be a string and is required’
},
text: {
bsonType: ‘string’,
description: ‘must be a string and is required’
},
creator: {
bsonType: ‘objectId’,
description: ‘must be an objectid and is required’
},
comments: {
bsonType: ‘array’,
description: ‘must be an array and is required’,
items: {
bsonType: ‘object’,
required: [‘text’, ‘author’],
properties: {
text: {
bsonType: ‘string’,
description: ‘must be a string and is required’
},
author: {
bsonType: ‘objectId’,
description: ‘must be an objectid and is required’
}
}
}
}
}
}
}
});
db.runCommand ( { collMod: “collectionX”, } )
collMod = collection modifier
db.runCommand({ collMod: 'posts', validator: { $jsonSchema: { bsonType: 'object', required: ['title', 'text', 'creator', 'comments'], properties: { title: { bsonType: 'string', description: 'must be a string and is required' }, text: { bsonType: 'string', description: 'must be a string and is required' }, creator: { bsonType: 'objectId', description: 'must be an objectid and is required' }, comments: { bsonType: 'array', description: 'must be an array and is required', items: { bsonType: 'object', required: ['text', 'author'], properties: { text: { bsonType: 'string', description: 'must be a string and is required' }, author: { bsonType: 'objectId', description: 'must be an objectid and is required' } } } } } } }, validationAction: 'warn' (ORRRRR ERROR QUE É O PADRÃO SE NAO ESPECIFICAR) });
insertOne ( )
x
insertMany ( )
x
insert ( )
+ mongoimport
insert é o antigo, dá muito problema, evitar usar
usar insertOne e insertMany
db. dropDatabase ( )
db. collectionX.drop ( )
deleta a database em uso atual
deleta a collectionX
insertMany is “ordered” insert
(default behavior)
if you insert [ {1}, {2}, {3} ], what happens if {2} got error?
MongoDB insere somente o {1} porque não faz rollback e nem continua a inserir
Como mudar isso?
db.collectionX.insertMany ( [ {1}, {2}, {3} ], {ordered: false} )
Desta forma vai inserir { 1 } e { 3 } porque o último não tem erro
ordered: true é o default
writeConcern
{ w: 1, wtimeout: 666, j true}
w = write, 1 significa que vai escrever
wtimeout = define o tempo que dá erro se não conseguir escrever no servidor
j = journal , se true usa ele, se undefined não usa ele
journal é o backup de “to do list”
…{writeConcern: {w:1, j: true}})
Como importar .json pro mongo
mongoimport original.json -d movieData -c movies –jsonArray –drop
1) sair do mongo (exit)
2) abrir powershell / terminal
3) navegar até onde está o arquivo (cd etc)
4) mongoimport fileX.json -d databaseX -c collectionX –jsonArray –drop
- -jsonArray (adiciona tudo)
- drop (deleta o que estiver naquela databse se existir)
Comparison Operators
db.collectionX.find ( { key1: {$xx: valueX} } )
$eq Matches values that are equal to a specified value.
$gt Matches values that are greater than a specified value.
$gte Matches values that are greater than or equal to a specified value.
$in Matches any of the values specified in an array.
$lt Matches values that are less than a specified value.
$lte Matches values that are less than or equal to a specified value.
$ne Matches all values that are not equal to a specified value.
$nin Matches none of the values specified in an array.
What this command works for:
db.movies.find({“rating.average”: {$gt: 7}}).toArray()
Na database atual (db), na coleção movies, procura e retorna (find), todos os campos em que average que está dentro de ratingo tem valor maior que 7 ($gt = greater than). Todos os valores são retornados toArray() (ou seja, até o final do documento, e automaticamente no formato .pretty() )
db.movies.find({“rating.average”: {$gt: 7}}).toArray()
Na database atual (db), na coleção movies, procura e retorna (find), todos os campos em que average que está dentro de ratingo tem valor maior que 7 ($gt = greater than). Todos os valores são retornados toArray() (ou seja, até o final do documento, e automaticamente no formato .pretty() )
O que o comando abaixo faz:
db.movies.find( {runtime: {$in: [30, 42] } } ).toArray ( )
Retorna todos os filmes com tempo de 30 ou 42, não retorna 31, 29, 43, etc…
$nin retornaria exatamente o contrário
db.movies.find( {runtime: {$in: [30, 42] } } ).toArray ( )
Retorna todos os filmes com tempo de 30 ou 42, não retorna 31, 29, 43, etc…
$nin retornaria exatamente o contrário
…find().count()
quantidade que retornaria
db.movies.find ( { $or: [ {“rating.average”: {$lt: 5} }, {“rating.average”: {$gt: 9.3} } ] } ).toArray ( )
retorna todos os filmes com nota menor que 5 ou nota maior que 9.3
$nor seria o contrário
(todos documentos não inclusos acima)
db.movies.find( {$and: [ {“rating.average”: {$gt: 9} }, {“genres”: “Drama”} ] } ).toArray ( )
(método antigo)
db.movies.find ( {“rating.average”: {$gt: 9}, “genres”: “Drama”} ).toArray ( )
(método atual)
retorna todos os filmes com gênero drama e nota maior que 9
$and é necessário quando vai usar dois filtros do mesmo campo (mesma key)
db.movies.find ( {runtime: { $not: { $eq: 60 } } } ).pretty ( )
local do $not
db.collectionX.find ( { keyX: {$exists: true} } ) .pretty ( )
mostra todos os documentos da collectionX que possuem uma keyX
se fosse false, mostraria todos documentos que nao tem keyX
db. collectionX.find ( { keyX: {$exists: true} } ) .pretty ( )
db. collectionX.find ( { keyX: {$exists: true, $ne: null} } ) .pretty ( )
mostra todos os documentos da collectionX que possuem uma keyX
se fosse false, mostraria todos documentos que nao tem keyX
acrescentar $ne (not equal) null para não aparecer campos em branco
db.collectionX.find ( { keyX: {$type: “number” } } ).pretty ( )
Retorna todos os documentos em que na keyX temos um number
39724384 = number "38749847987" = string
$regex _> search for text
> db.movies.find ( { summary: {$regex: /musical/ } } )
retorna todos documentos que contem musical no summary
db.collectionX.find ( {$expr: {$gt: [“$keyX”, “$keyY”] } } )
retorna todos documentos em que keyX > keyY
db.collectionX.find({“keyX.subkeyX”: “stringX”}).pretty()
Retorna tudo que nao subkeyX (que faz parte da keyX) contem a stringX
db.collectionX.find({keyX: {$size: 666}}).pretty()
Retorna todos documento em que a keyX contem 666 subkeys ou 666 strings numa lista [ ]
db.collectionX.find( {keyX: {$all: [“subkeyY”, “subkeyZ”] } } ).pretty()
procura tudo que tem subkeyY e subkeyZ na keyX, SEM PRECISAR SER NESSA ORDEM (Y e Z)
db.collectionX.find( {keyX: {$elemMatch: {keyX: “valueX”, keyY:”valueY”}}}).pretty()
retorna todos os documentos que preenchem os dois critérios, tanto na keyX quanto na keyY
db.collectionX.find(kkk).next()
retorna o próximo documento que preenche os critérios kkk
dataCursor.forEach(doc => {printjson(doc)})
const cursor = db.collectionX.find ( )
retorna todos os documentos que ainda não retornaram
cria um cursor
db.collectionX.find ( ).sort ( {“rating.average”: 1} ).pretty ( )
Organiza os itens em ordem crescente do rating.average
se -1, ordem descendente
pode colocar um segundo, terceiro, etc critério de organização pra desempatar, só colocar virgula dentro da chave
db.movies.find().sort().skip(666).limit(67).pretty()
Pula os 666 primeiros documentos desta pesquisa e retorna os 67 seguintes
os comandos são executados na ordem em que aparecem ? não nesse caso
db.collectionX.find( { }, {keyX: 1, keyY: 1, _id: 0} )
retorna todos os documentos da coleção porém só os campos keyX e keyY de cada um.
1 é sim, valor padrão somente pra _id
0 é não, valor padrão para os demais
Projection
db.collectionX.find ( {keyX: “valueX”}, {“keyX.$”: 1 } ).pretty()
não entendi muito bem
retorna somente o valueX da keyX, se a keyX tiver também outra string, essa não retorna
db.collectionX.find ( {“keyX.subkeyX”: {$gt: 3 } }, { keyY: {$slice: [ 5, 7 ] }, keyZ: 1 } ).pretty()
procuras os documentos em que na subkeyX de keyX os valores são maiores que 3, aí retorna a keyZ (1), a _id (padrão é 1) e da keyY pula as 5 primeiras strings, retornando as 7 seguintes (6a a 12a), nao retorna as demais se existirem
db.collectionX.updateOne ( {keyX: “valueX”}, {$set: {keyY: [“valueY”] } } )
Overwrite keyY onde keyX=valueX, não altera keyX, keyZ, etc…
mesmo raciocínio para updateMany
db.collectionX.updateOne( {keyX:”valueX”}, {$inc: {keyY: 88} } )
Aumenta em 88 o valor da keyY no documento em que keyX=valueX
$inc = increment
se usar número negativo vai diminuir
db.collectionX.updateOne( {keyX:”valueX”}, {$max: {keyY: 88} } )
Seta em 88 o valor da keyY no documento em que keyX=valueX, se o valor de keyY anterior for menor que 88
$max altera se o novo valor for maior
$min altera se o novo valor for menor
$mul multiplica pelo valor que fornecemos
db.collectionX.updateMany( { keyX: “valueX”} , {$unset: { keyY: “”} } )
retira a keyY de todos os keyX=valueX, é diferente de setar null
”” pode ser qualquer string, numero, não importa no unset
db.collectionX.updateMany( { keyX: “valueX”} , {$rename: { keyY: “keyZ”} } )
muda o nome de keyY para keyZ
UPSERT
db.collectionX.updateOne ( {keyX= 666}, {$set: {keyY: [“bla”, “kkk”, “LOL”] } }, { upsert: true } )
acrescenta keyY na keyX=666, mas se não existir documento keyX=666 vai criar esse documento
valor padrão de upsert é false
db.collectionX.updateMany ( { keyX: {$elemMatch: { subkeyY: “valueY”, subkeyZ: “valueZ”}, {$set: {“keyX.$.subkeyW”: newvalueW ).pretty()
Atualiza todos os documentos em que na keyX temos uma subkeyY=valueY e subkeyZ=valueZ dentro. A esta keyX acrescentamos agora uma subkeyW sem apagar as outras subkeys.
…{$inc: { “keyX.$[].subkeyY”: 88} }
aumenta em 88 o valor de todas as subkeyY dentro da lista de keyX
db.colX.updateMany ( {“keyX.subkeyX”: {$gt: 55} }, {$set: {“keyY.$[qwert].subkeyY”: “asdfg”}}, {arrayFilters: [ { “qwert.subkeyZ”: {$gt 33} } ] } )
onde tem subkeyX de keyX maior que 55, cria a subkeyY em keyY com valor “asdfg”, em todos os lugares em que subkeyZ for maior que 33.
db.colX.uptdateOne ( { keyX: “valueX” }, {$push: {keyY: “valueY”} )
db.colX.uptdateOne ( { keyX: “valueX” }, {$push: {keyY: [
{ subkeyW: “valueW” }, {subkeyW: “valueK”} , $sort: {subkeyW: -1} ] } )
$push coloca novo elemento na array
acrescenta o valueY na keyY além dos que já existem lá, desde que keyX=valueX nesse documento
acrescenta os valueK e valueW na subkeyW
db.colX.updateOne( { keyX: valueX } , {$pull : {keyY: {“subkeyY”: “valueY” } } } )
Remove tudo que tem valueY na subkey Y desde que keyX = valueX no documento
db. colX.updateOne( { keyX: valueX } , {$pop : {keyY: 1 } )
db. colX.updateOne( { keyX: valueX } , {$pop : {keyY: -1 } )
exclui o último item de keyY
exclui o primeiro item de keyY
$push
vs
$addToSet
o primeiro pode repetir objeto inserido
o segundo só permite inserir se for único
db. colX.deleteOne ( {keyX: “valueX” } )
db. colX.deleteMany ( {keyX: “valueX” } )
deleta todos o primeiro ou todos em que keyX=valueX
db.colX.deleteMany( { } )
ou
db.colX.drop ( )
deleta todos os documentos da colX
index
acelera localizar dados, organizados
faz insert ser mais lento
usar index só quando faz sentido
db.colX.explain(“executionStats”).find(xxxxxx)
retorna com detalhes como foi feita a busca
db.colX.createIndex({“keyX”: 1})
dropIndex deleta ele
cria index e faz busca ficar mais rápida
1 para ascendente
-1 para descendente
valueX poderia ser keyX.subkeyY etc
db.colX.createIndex({“keyX”:1, keyY:1})
will index for what kind of searches?
keyX and keyY
keyX alone
NOT for keyY alone
db.colX.createIndex({“keyX”:1, keyY:1, keyZ})
will index for what kind of querys?
keyX and keyY and keyZ
keyX and keyY
keyX alone
NOT for keyY alone, keyZ alone, keyY and keyZ
pode usar pra sort, sort não pode ser usado para muitos dados (limite 32MB)
db.colX.getIndexes ( )
retorna todos os indexes da coleção, incluindo _id que é feito de default
db.colX.createIndex({keyX: 1}, {unique: true})
dá mensagem de erro se tiver duas keyX com o mesmo valueX em 2 documentos diferentes da mesma coleção.
útil pra evitar email repetido de cadastro, por exemplo
db.colX.createIndex({“keyX”: 1}, {partialFilterExpression: {keyY: “valueY”}})
Cria um index em ordem ascendente dos valores de keyX mas somente nos documentos em que KeyY=valueY. keyX poder ser igual keyY.
db.colX.createIndex( {valueX: 1}, {unique: true, partialFilterExpression: {valueX: {$exists: true} } } )
cria um index em que valueX está em ordem ascendente
caso não colocasse a partialFilterExpression, se fosse criar um documento sem a keyX daria erro
db.colX.insertOne({keyX: “xxxxx”, createdAt: new Date ( ) } )
além do campo keyX cria o campo createdAt com valor semelhante ao seguinte:
“createdAt” : ISODate(“2020-04-14T00:35:46.378Z”)
db.colX.createIndex({createAt: 1}, {expireAfterSeconds: 10})
não funciona com subkeyX
tudo que tiver createAt com algum valor de tempo, sera deletado 10 segundos após ser inserido na coleção
explain(“xxxxx”)
3 opções:
“queryPlanner”: summary + winning plan
“executionStats”: detailed summary + winning plan
“allPlansExecution”: detailed plan + winning plan detailed decision process
IXSCAN vs COLLSCAN
Pra avaliar o mais rápido: Milliseconds Process Time
index vs sem index
MongoDB testa o plano mais rápido para query (index ou não e qual index) através dos 100 primeiros resultados, e os armazena por um período. Qual período?
Write threshold (1000)
Index rebuilt
Other indexes added or removed
Server restarted
db.colX.createIndex( { keyX: “text” } )
Salva todas as key-words como em uma array, tudo é guardado em lower case
db.colX.find( { $text: { $search: “xxxxx” } } )
xxxxx é a string que estamos procurando
não precisa informar keyX no find porque só pode um text por coleção
db. colX.find( { $text: { $search: “xxxxx yyyyy” } } )
db. colX.find( { $text: { $search: “"xxxxx yyyyy”" } } )
procura por textos com xxxxx ou yyyyy
procura por textos com exatamente “xxxxx yyyyy”
db.colX.find( { $text: { $search: “xxxxx yyyyy” } } , { score: {$meta: “textScore”} } ).sort ( { score: { $meta: “textScore” } } ). pretty ( )
Returns the score associated with the corresponding $text query for each matching document. The text score signifies how well the document matched the search term or terms. If not used in conjunction with a $text query, returns a score of 0
E pelo sort, organiza pelo score
db.colX.dropIndex(index_name)
deleta o index
db.colX.createIndex( { keyX: “text”, keyY: “text” } )
cria index com palavras chaves de keyX e keyY (é um jeitinho pra ter mais de um index por coleção)
db.colX.find( { $text: { $search: “xxxxx -yyyyy” } } )
procura por tudo que tem xxxxx mas não tem yyyyy
“xxxxx -yyyyy”
db.colX.createIndex( { keyX: “text”, keyY: “text” }, {default_language: “portuguese”, weights: { keyX: 3, keyY: 12} } )
pode escrever pt, en, etc no lugar de portuguese, útil pra tirar e, com, sim, não, etc…
o peso da keyY é 4 vezes keyX pra calcular o score
db.colX.createIndex( { keyX: “text” }, {background: true} )
Building indexes:
FOREGROUND: collection is locked during index creation and is faster (padrão)
BACKGROUND: not locked but slower
default é false
db.persons.aggregate([{$match: {gender: “female”}}])
db.persons.aggregate([
{$match: {gender: “female”}}
])
retorna mas com “it”
são sinônimos
db.persons.aggregate([ { $match: { gender: "female" } }, { $group: { _id: { estado: "$location.state"}, totalPessoas: { $sum: 1 } } }, { $sort: { totalPessoas: -1 }} ]).pretty();
português é o que criei na hora de executar, inglês é o que já existia na database
agrega as pessoas do sexo feminino por estados, conta a quantidade e depois ordena em ordem descendente de quantidade
db.persons.aggregate([ { $match: { "dob.age": { $gt: 50 } } }, { $group: { _id: { sexo: "$gender"}, totalPessoas: { $sum: 1 }, mediaIdade: { $avg: "$dob.age" } } }, { $sort: { totalPessoas: -1 }} ]).pretty();
{ "_id" : { "sexo" : "female" }, "totalPessoas" : 1125, "mediaIdade" : 61.90577777777778 } { "_id" : { "sexo" : "male" }, "totalPessoas" : 1079, "mediaIdade" : 62.066728452270624 }
db.persons.aggregate([ { $match: { "dob.age": { $gt: 50 } } }, { $group: { _id: { sexo: "$gender"}, totalPessoas: { $sum: 1 }, mediaIdade: { $avg: "$dob.age" } } }, { $sort: { totalPessoas: -1 }} ]).pretty();
portugues é o que eu criei na hora do comando, ingles é o que já existia
{ "_id" : { "sexo" : "female" }, "totalPessoas" : 1125, "mediaIdade" : 61.90577777777778 } { "_id" : { "sexo" : "male" }, "totalPessoas" : 1079, "mediaIdade" : 62.066728452270624 }
selecionou pessoas com mais de 50 anos agrupou por sexo somou o total por sexo calculou a média por sexo organizou em ordem decrescente de total de pessoas por sexo
db.persons.aggregate([ { $project: { _id: 0, gender: 1, fullName: { $concat: [ { $toUpper: { $substrCP: ['$name.first', 0, 1] } }, { $substrCP: [ '$name.first', 1, { $subtract: [{ $strLenCP: '$name.first' }, 1] } ] }, ' ', { $toUpper: { $substrCP: ['$name.last', 0, 1] } }, { $substrCP: [ '$name.last', 1, { $subtract: [{ $strLenCP: '$name.last' }, 1] } ] } ] } } } ]).pretty();
{ “gender” : “male”, “fullName” : “Zachary Lo” }
{ “gender” : “male”, “fullName” : “Carl Jacobs” }
{ “gender” : “female”, “fullName” : “پریا پارسا” }
{ “gender” : “female”, “fullName” : “Louise Graham” }
{ “gender” : “female”, “fullName” : “Shona Kemperman” }
{ “gender” : “female”, “fullName” : “Maeva Wilson” }
{ “gender” : “male”, “fullName” : “Harvey Chambers” }
{ “gender” : “female”, “fullName” : “Olav Oehme” }
{ “gender” : “male”, “fullName” : “Isolino Viana” }
{ “gender” : “female”, “fullName” : “Mestan Kaplangı” }
{ “gender” : “female”, “fullName” : “Madeleine Till” }
{ “gender” : “female”, “fullName” : “Katie Welch” }
{ “gender” : “female”, “fullName” : “Sandra Lorenzo” }
{ “gender” : “male”, “fullName” : “بنیامین سالاری” }
{ “gender” : “male”, “fullName” : “Gideon Van drongelen” }
{ “gender” : “female”, “fullName” : “Anne Ruiz” }
{ “gender” : “female”, “fullName” : “Andreia Arnaud” }
{ “gender” : “male”, “fullName” : “Elijah Lewis” }
{ “gender” : “female”, “fullName” : “Maeva Grewal” }
{ “gender” : “female”, “fullName” : “Gonca Alnıaçık” }
db.friends.aggregate([
{ $unwind: “$hobbies” },
{ $group: { _id: { age: “$age” }, allHobbies: { $addToSet: “$hobbies” } } }
]).pretty();
$push parece com $addToSet mas duplica valores
Tira o que esta dentro de uma lista em hobbies e coloca diretamente em hobbies
db.persons .aggregate([ { $bucket: { groupBy: '$dob.age', boundaries: [18, 30, 40, 50, 60, 120], output: { numPersons: { $sum: 1 }, averageAge: { $avg: '$dob.age' } } } } ]) .pretty();
db.persons.aggregate([ { $bucketAuto: { groupBy: '$dob.age', buckets: 5, output: { numPersons: { $sum: 1 }, averageAge: { $avg: '$dob.age' } } } } ]).pretty();
O primeiro classifica as pessoas por grupo de idade, 18 a 30 anos, 40 a 50 anos, etc
O segundo classifica em 5 partes as pessoas por idade, ele tenta fazer as 5 partes iguais, mas sempre as pessoas com a mesma idade ficam no mesmo grupo
db.persons.aggregate([ { $match: { gender: "male" } }, { $project: { _id: 0, gender: 1, name: { $concat: ["$name.first", " ", "$name.last"] }, birthdate: { $toDate: "$dob.date" } } }, { $sort: { birthdate: 1 } }, { $skip: 10 }, { $limit: 10 } ]).pretty();
procura os homens mais velhos, pula os 10 mais velhos e retorna os 10 seguintes
db.persons.aggregate([ { $project: { _id: 0, name: 1, email: 1, birthdate: { $toDate: '$dob.date' }, age: "$dob.age", location: { type: 'Point', coordinates: [ { $convert: { input: '$location.coordinates.longitude', to: 'double', onError: 0.0, onNull: 0.0 } }, { $convert: { input: '$location.coordinates.latitude', to: 'double', onError: 0.0, onNull: 0.0 } } ] } } }, { $project: { gender: 1, email: 1, location: 1, birthdate: 1, age: 1, fullName: { $concat: [ { $toUpper: { $substrCP: ['$name.first', 0, 1] } }, { $substrCP: [ '$name.first', 1, { $subtract: [{ $strLenCP: '$name.first' }, 1] } ] }, ' ', { $toUpper: { $substrCP: ['$name.last', 0, 1] } }, { $substrCP: [ '$name.last', 1, { $subtract: [{ $strLenCP: '$name.last' }, 1] } ] } ] } } }, { $out: "transformedPersons" } ]).pretty();
faz toda essa série de procura etc e no final transforma isso tudo numa nova coleção com $out
NUMBERS
Integers (Int32) - integers from -2.147.483.648 até 2.147.483.647
(2 bilhões)
COMANDO: NumberInt(666)
Longs (int64) - full numbers
-9.223.372.036.854.775.808 até -9.223.372.036.854.775.808
(9 quinquilhões)
COMANDO: NumberLong(666)
Doubles (64bit) - decimal places
Decimal values are approximated (similar ao Python)
DEFAULT
“High precision doubles” (128bit) - decimal places
Decimal values are stored with high precision (34 decimal digits)
COMANDO: NumberDecimal(6.66666)
Default no MongoDB é Doubles (64bit), no Python é Integer (Int32)
Se não especificar no MongoDB, ele tenta usar o melhor possível
Cuidado ao colocar números entre “ “.
Serão tratados como texto, impossível fazer cálculos com eles.
Quando fizer conta tem que especificar o tipo, caso contrário trata tudo como default (doubles).
SECURITY CHECKLIST (6 no total, completar com 3)
Auditing (who did what)
Server & Network Config and Setup
Backups & Software Updates
Authentication & Authorization
Transport Encryption
Encryption at Rest
Authentication - who (identify enable users)
Authorization - what (roles, privileges)
Users != Client
Privileges: Resources (where) + Actions (what)
Groups of roles
USERS ROLES
Administrator
Developer/App
Data Scientist
Administrator: manage database configuration, create users, NOT NECESSARILY insert or query data
Developer/App: CRUD, NOT NECESSARILY config, create users
Data Scientist: query data NOT NECESSARILY config, users, create, update, delete
db.colX({user: “userX”, pwd “passwordX”, roles: [“readWrite”]})
userX com função “CRUD” na colX
db.updateUser(“userX”, {roles: [“oldRoleX”, {role: “oldRoleX”, db: “newColY]})
Usuário que tinha RoleX na oldColX agora tem o mesmo RoleX na newColY também
getUser(“userX”)
retorna os roles do usuário
What influences Performance?
Capped Collections
Replica Sets
Sharding
MongoDB Server Deployment
DEVELOPER / DB ADMIN:
Efficient Queries / Operations
Indexes
Fitting Data Schema
DB ADMIN / SYSTEM ADMIN
Hardware & Network
Sharding (Particionar Dados)
Replica Sets
db.createCollection(“colX”, {capped: true, size 66666, max: 666})
66666 - size in bytes
666 - máximo de documentos permitidos
Capped Collections: limite de dados, deleta os dados antigos para armazenar os novos
db.createCollection(“colX”, {capped: true, size 66666, max: 666})
66666 - size in bytes
666 - máximo de documentos permitidos
CAPPED COLLECTIONS: limite de dados, deleta os dados antigos para armazenar os novos
Client (Shell Driver) —(write)—> MongoDB Server —(write)—> Primary Node (pode ter Secundary Nodes formando Replica Set)
Backup / Fault Tolerancy
Improve Read Performance
If Primary Node goes offline, Secundaries ellect a new Primary
Secundaries can be configured to be read
Sharding (Horizontal Scaling)
Data is DISTRIBUTED (not replicated) across Shards
Queries are run across all Shards
mongos (Router) is responsible to split information to the right Shard
Shard key pra escolher pra onde vai
DEPLOYING A MONGODB SERVER
Manage Shards, Manage Replica Sets, Secure User/Auth Setup, Protect Web Server / Network, Encryption (Transportation & Rest), Regular Backups, Update Software
Melhor usar o Atlas DB do que aprender isso tudo!
Free option!
Transactions (3.6 = Free Version, 4.0 Paid)
Transaction: 0 ou 100% do comando executado
Transcactions is a “to do list”
Gives Atomacity to many documents (not only one document as usually)
const session = db.getMongo().startSession()
session.startTransaction()
const collectionXCol = session.getDatabase(“databaseX”).collectionX
(pode executar pra quantas collections quiser)
bla
blu
kkk
session. commitTransaction() => executa bla, blu e kkk
session. abortTransaction() => cancela todas essas operações
SHELL
Configure Database
Create Collections
Create Indexes
DRIVER
CRUD Operations
Aggregation Pipelines
Stitch
Serveless Plataform for Building Applications