Mongo Db - PHP Day Workshop
Upcoming SlideShare
Loading in...5
×
 

Mongo Db - PHP Day Workshop

on

  • 5,110 views

A presentation about non-relational databases focussing on mongodb and how to implement a simple blog backend using it with php.

A presentation about non-relational databases focussing on mongodb and how to implement a simple blog backend using it with php.

Statistics

Views

Total Views
5,110
Views on SlideShare
4,977
Embed Views
133

Actions

Likes
5
Downloads
99
Comments
2

5 Embeds 133

http://www.sanainside.com 93
http://www.slideshare.net 27
http://www.phpes.org 11
http://64.233.169.132 1
http://translate.googleusercontent.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Mongo Db - PHP Day Workshop Mongo Db - PHP Day Workshop Presentation Transcript

  • WORKSHOP ::: 1º PHP-DAY MongoDB: alternativa intuitiva e não-relacional ao Mysql Diego Sana
  • Sobre mim
    • Desenvolvedor e empreendedor web há 10 anos
    • Graduando em Ciência da Computação na UFES
      • 1999: freemp3.com.br
      • 2000: Central da Música (.com.br)
        • Premiado pelo iBest em 2001 e 2003
      • 2003: Primeiro contato com PHP
      • 2004: Flogão.com.br (PHP, databases, escalabilidade)
      • 2007: Power.com (idem)
      • 2009: Restarting (bye-bye mysql, thanks for all the fish)
    • Blog: www.sanainside.com, Twitter: @sanainside
  • Sumário
    • Bancos de dados relacionais e seus problemas
    • Bancos de dados não-relacionais (e o "movimento" NOSQL)
    • MongoDB: o que é, quem faz, filosofia, funcionalidades, pros, contras, por que usar
    • MongoDB: Botando a mão na massa
    • MongoDB: indo além
    View slide
  • Motivação
    • Os bancos de dados relacionais se tornaram o "martelo" da indústria de armazenamento de dados
    • Facilidade para entender o modelo relacional de dados e consultá-los
    • Versatilidade
    View slide
    • Na computação, tudo que é versátil demais, é menos eficiente
    • Bancos relacionais não "casam" com o paradigma OO. Necessidade de ORMs (“O Vietnã da Ciência da Computação“)
    • Concebidos no final da década de 70, quando não existia a ... WEB!!!
    Porém…
    • RDBMS (como o mysql) são usados certamente em 99,9% dos sites
    • 99,9% dos sites não precisam de boa parte de suas funcionalidades (ACID, triggers, stored procedures quem?)
    • Apesar da versatilidade, não são tão flexíveis
    • Pra escalar, só fazendo muita magia e rasgando o manual (foda-se normalização, fodam-se chaves estrangeiras, fodam-se os joins)
    RDBMS e a web …
    • RDBMS sendo usados de forma não-relacional. Por que usá-los então?
    • Engenheiros de grandes empresas da WEB desenvolveram suas próprias databases para resolver seus problemas de escala
    • Algumas open-source, e as que não são foram "clonadas" por projetos Open-Source
    • "Cool Kids" chamam esse "movimento" de NoSQL
    Podemos fazer melhor: NoSQL
    • Usada internamente em vários serviços do Google
    • Escalável, tolerante a falhas e orientada colunas/linhas (híbrida)
    • Disponível para uso com Google App Engine
    • Clones open-source: HBase e HyperTable
    Exemplos: BigTable
    • Criada pela Amazon.com
    • Database chave / valor, alta escalabilidade / disponibilidade
    • Disponível para uso via Amazon Web Services ("SimpleDB")
    • Clone Open-source: Project Voldemort (Linkedin)
    Exemplos: Dynamo
    • Projeto Open-Source iniciado por empresa contratada para desenvolver LiveJournal.com
    • Na verdade um camada de cache chave/valor, alta escalabilidade/disponibilidade
    • MemcacheDB = Memcache + BerkeleyDB = persistência em disco
    • Redis = Memcache não-volátil e com mais estruturas de dados (strings, listas, conjuntos)
    Exemplos: Memcache
    • Apache Foundation. Orientado a documentos, schema free
    • Acesso via REST, documentos JSON
    • ACID
    • Querys precisam ser pré-definidas (criação de views)
    Exemplos: CouchDB
    • Escalabilidade facilitada
    • Alta-performance
    • Modelos de dados simplificados/limitados
    • Quase sempre querys simples, estilo "Select * from tabela where ID='xxx'"
    O que todos eles tem em comum
    • Um banco de dados de alta performance, escalável, e schema-free orientado a documentos
    • Em uso há quase 2 anos. Beta desde fev/2009. Versão 1.0 GA em agosto/2009
    • Preenche lacuna entre as databases do tipo Chave / Valor (rápidas e escaláveis) e os tradicionais RDBMS (que tem mais funcionalidades)
    Mongo DB: o melhor dos dois mundos
    • Empresa americana 10gen, mesmo modelo da Mysql AB
    • Fundadores trouxeram experiência adquirida na DoubleClick
    Quem faz
    • Databases estão se especializando
    • O modelo orientado a documentos é de fácil implementação e gerenciamento, proporciona melhor performance
    • Redução de capacidades para maior performance é importante, mas há necessidade de mais funcionalidades que as providas por databases chave/valor
    Filosofia
    • Querys dinâmicas e mais parecidas com SQL
    • Suporte a índices, inclusive em vetores
    • Query profiling
    • Operadores $gt, $gte, $lt, $lte, $eq, $neq, $exists, $set, $mod, $where, $in, $inc, $pull, $push, $pop, $pushAll, $popAll
    Funcionalidades
    • Manipulação server-side de dados usando Javascript
    • GridFS para armazenamento eficiente de arquivos binários grandes
    • Escalabilidade via: replicação e auto-sharding (alpha)
    • Suporte a falhas: replicação master-master
    Funcionalidades
    • Alta performance (inserts/updates muito rápidos)
    • Excelente cache (pode eventualmente dispensar Memcache)
    • Escalabilidade (jura!?)
    • Documentos armazenados são objetos/Json/Whatever (die ORM!!!)
    • Schema-less = não precisa parar o site para adicionar uma nova coluna na tabela
    Pros
    • Schema-less usa mais espaço em disco
    • Databases limitadas a 2GB em sistemas 32 bit (ilimitadas em 64bit)
    • Crash-recovery não é automático
    • Apesar de estável e em uso por grandes sites, bugs ainda são frequentes (principalmente nos drivers)
    Contras
    • Aplicações web em geral que demandem boa performance de inserts/updates/reads
    • Armazenar dados de grande volume, baixo valor.
    • Logging / Analytics em Tempo Real
    • Armazenar diretamente objetos ou dados em Json (por ex: como os obtidos de APIs)
    Adequado para
    • Sistemas altamente transacionais (Mongo não garante atomicidade em transações)
    • Problemas que necessitem de querys SQL complexas
    • Business Intelligence
    Inadequado para
    • Mysql ou outro RDBMS atende plenamente
    • Ainda assim existem bons motivos para usar MongoDB:
      • Facilidade de lidar com os objetos
      • Melhor performance
      • É legal conhecer e implementar novas tecnologias
    Ei, mais eu só quero fazer o site da padaria do meu tio!!!
    • Databases
    • Coleções
    • Documentos
    • BSON
    Modelo de dados
    • Agrupamento físico de coleções
    • Um arquivo de namespaces (nomes de coleções e índices)
    • Arquivos de dados (pré-alocação: 64 MB -> 128MB -> 256MB -> 512 MB -> 1GB -> 2GB -> 2GB...)
    • 10k coleções/databases (limite configurável)
    Databases
    • Agrupamento lógico de documentos em uma database (equivale às tabelas do RDBMs)
    • Schema-free
    • Número ilimitado de documentos
    Coleções
    • Unidade de armazenamento (equivale às linhas do RDBMs)
    • Todos devem ter um _id único (em relação à coleção)
    • Tamanho máximo de 4MB (para objetos maiores, use GridFS)
    Documentos
    • Formato de armazenamento de dados de documentos ou objetos no MongoDB
    • "Binary JSON"
    • Permite representação de algumas formas de dados que não fazem parte do padrão JSON (Date / BinData, por exemplo)
    BSON
    • Binários disponíveis em 32/64 bit para Linux, Windows, OS X e Solaris
    • Versão 32 bit linux: http://downloads.mongodb.org/linux/mongodb-linux-i686-1.0.0.tgz
    • Demais versões direto em http://www.mongodb.org/display/DOCS/Downloads
    Baixando o MongoDB
    • Extrair conteúdo do arquivo mongodb-linux-i686-1.0.0.tgz para pasta /mongodb
    • Crie pasta /data/db e marque com permissão de escrita para o usuário desejado
    • Execute o daemon: /mongodb/bin/mongod run
    • Alternativa: usar um init script
      • Scripts para Ubuntu e Centos em www.sanainside.com/wp-content/uploads/2009/09/initscripts-mongodb.zip
    Instalação do Servidor MongoDB
    • Via pecl: pecl install mongo channel://pecl.php.net/mongo-0.9.5
    • Via GitHub: baixar source de http://github.com/mongodb/mongo-php-driver/tarball/master
      • Extrair conteúdo de tar.gz
      • Acessar pasta e digitar no console:
      • $ phpize
      • $ ./configure
      • $ sudo make install
    • Ao final, adicionar essa linha ao php.ini: extension=mongo.so
    • Reiniciar apache
    Instalação do Driver PHP
    • Shell : /mongodb/bin/mongo
    • Interface web: http://localhost:28017
    • Ferramentas para importar / exportar / backup / restore: [/mongodb/bin/] mongoimportjson, mongoexport, mongodump, mongorestore
    Incluso com MongoDB
    • Abrir conexão:
    • Por padrão, não há usuários nem senhas. Configure seu firewall (como iptables) para não deixar a porta exposta para ips indesejados
    • É possível adicionar autenticação individual para cada database, inserindo usuário/senha na coleção "admin".
    Usando MongoDB com PHP $conn_mongodb = new Mongo(); // Assume mongod rodando em localhost:27017 (default)
    • $db = $conn_mongodb->selectDB("nomedadatabase");
    • $col = $db->selectCollection("nomedacolecao");
    • $col->insert($doc);
    • $col->save($doc);
    • $cursor = $col->find($id);
    • $cursor->getNext();
    Alguns métodos básicos
    • Vamos implementar funções CRUD de um sistema de blogging com:
      • Multi-usuários
      • Posts
      • Comentários
      • Tags
      • Contador de Visitas
      • Lista de amigos
    Implementando um MongoLog 
    • Database: blog
    • Coleções: users, posts, friends
    • Cada documento da coleção posts conterá não só os textos de um post, como também os comentários, as tags e o contador de visitas (“embed documents”)
    Modelagem
  • Criando e inserindo na coleção "users"
    • Não é necessário criar database/coleção previamente
    • Um documento da coleção usuário:
    • Pra inserir:
    • Se seu documento não tiver um "_id", mongodb irá atribuir um MongoID automaticamente (12 bytes)
    $doc = array("_id" => 1, "email" => "meu@email.com", "nome" => "Joaozinho", "nivel" => "admin_supremo"); $conn_mongodb->selectDB("blogs")->selectCollection("users")->save($doc);
  • Fazendo uma consulta
    • Assim como documentos, querys também são especificadas como array
    • Retornar todos os campos de todos usuários com nome Joaozinho:
    • Retornar o email dos usuários com nome Joaozinho
    $query = array("nome" => "Joaozinho"); $cursor = $conn_mongodb->selectDB("blogs")->selectCollection("users") ->find($query) $query = array("nome" => "Joaozinho"); $fields = array("email" => true); $cursor = $conn_mongodb->selectDB("blogs")->selectCollection("users") ->find($query,$fields);
  • find() vs findOne()
    • find() retorna cursor para resultados encontrados:
    • findOne() retorna o documento (apenas um)
    • find(), sem parametros, retorna cursor p/ todos docs
    $query = array(“_id” => “1”); $col = $conn_mongodb->selectDB("blogs")->selectCollection("users"); $cursor = $col->find($query); while($cursor->hasNext()) { $doc = $cursor->getNext(); } $query = array(“_id” => “1”); $col = $conn_mongodb->selectDB("blogs")->selectCollection("users"); $doc = $col->findOne($query);
  • Inserindo um post
    • Inicialmente o documento precisa conter apenas os campos do post
    • Ao fazer insert(), driver atribui MongoID em $doc[“_id”]
    • Update para inserir tags. Dois métodos:
    $doc = array(“titulo” => “Titulo do meu post”, “texto” => “Aqui vai meu textículo”, “data” => new MongoDate(), “ idAutor” => 1)); $col->insert($doc); // método português: adiciona tags ao array $doc e o salva no db: $doc[“tags”] = array(“teste”,”mongodb”); $col->save($doc) // método l337: usando o “modificador” $set $query = array(“_id” => $doc[‘_id’]); $updatefields = array(‘$set’ => array(“tags” => array(“teste”,”mongodb”) )); $col->update($query,$updatefields,true);
  • Inserindo comentários num post
    • Assim como tags, comentários também serão inseridos no documento do post, como um vetor de comentários
    • Usaremos o modificador “$push”, que permite inserir novos valores em um array sem necessidade de fornecer o array na query
    • Parametro 3 em update() aceita os valores “true” ou “false” (bool), e determina que, caso não exista o documento com o _id passado no parametro 1, ou o campo passado no parametro 2, Mongo faça a criação
    $comentario = array(“nome” => “Comentador”, “email” => “me@obriga.com” “ comentario” => “Que legal”); $query = array(“_id” => $doc[“_id”]); $updatefields = array(‘$push’ => array(“comentarios” => $comentario)); $col->update($query,$updatefields,true);
  • Contador de Visitas
    • Visitas serão contadas em um campo no documento de posts
    • Usaremos o modificar “$inc”, que permite incrementar o valor de um campo
    • No exemplo acima, fizemos um incremento de +1 no campo visitas. Para fazer um incremento de +2, usaríamos:
    $query = array(“_id” => $doc[“_id”]); $updatefields = array(‘$inc’ => array(“visitas” => 1)); $col->update($query,$updatefields,true); $updatefields = array(“$inc” => array(“visitas” => 2));
  • Lista de amigos
    • Uma lista de amigos de um usuário pode ser um documento cujo “_id” seja o “_id” dele na coleção “users” e com um campo “ids” contendo um array de “_id” de seus amigos
    • Usaremos o modificador “$push”, assim como fizemos nos comentários:
    • Em vetores numéricos, podemos usar o modificador “$pull” para excluir um valor:
    $col = $db->selectCollection(“friends”); $idUser = 1; $idFriend = 2; $query = array(“_id” => $idUser); $updatefields = array(‘$push’ => array(“ids” => $idFriend)); $col->update($query,$updatefields,true); $query = array(“_id” => 1); $updatefields = array(“$pull” => array(“ids” => 2)); $col->update($query,$updatefields);
  • Contador, paginação e ordenação
    • Contar o número de posts
    • Obter todos os posts em ordem cronológica
    • Obter um post, pulando os dois primeiros
    $col = $db->selectCollection(“posts”); $cursor = $col->find(); $cursor_ascendente = $cursor->sort(array(“data” => 1)); $cursor_descendente = $cursor->sort(array(“data” => -1)); $col = $db->selectCollection(“posts”); $contador = $col->count(); $cursor = $col->find(); $cursor->sort(array(“data” => -1)); $cursor->skip(2); $cursor->limit(1);
  • Querys usando operadores
    • Obter posts com mais de 2 visitas:
    • Obter todos os posts sem comentários
    • Obter todos os posts com a tag “mongo”
    $col = $db->selectCollection(“posts”); $query = array(“visitas” => array(‘$gt’ => 2)) $cursor = $col->find($query); $col = $db->selectCollection(“posts”); $query = array(“comentarios” => array(‘$exists’ => false)) $cursor = $col->find($query); $col = $db->selectCollection(“posts”); $query = array(“tags” => array(‘$in’ => “mongo”)) $cursor = $col->find($query);
  • Querys usando operadores
    • Obter posts contendo entre 1 e 3 visitas:
    • Obter todos os posts com 2 comentários
    • Obter posts com uma das tags: “teste”, “mongo”, “php”
    $col = $db->selectCollection(“posts”); $query = array(“visitas” => array(‘$gt’ => 1, ‘$lt’ => 3)) $cursor = $col->find($query); $col = $db->selectCollection(“posts”); $query = array(“comentarios” => array(‘$size’ => 2)) $cursor = $col->find($query); $col = $db->selectCollection(“posts”); $query = array(“tags” => array(‘$in’ => array(“mongo”, “teste”, “php”)) $cursor = $col->find($query);
  • Índices
    • A query anterior pode ser otimizada adicionado um índice ao campo “tags”:
    • Em campos em que a ordem importa, pode-se determinar a mesma num índice:
    • Para saber se uma query está usando índices, use explain:
    $col = $db->selectCollection(“posts”); $col->ensureIndex(“tags”); $col = $db->selectCollection(“posts”); $col->ensureIndex(array(“data” => 1)); // índice com ordem crescente $col->ensureIndex(array(“data” => -1)); // índice com ordem decrescente $query = array(“tags” => “mongodb”); $cursor = $col->find($query); var_dump($cursor->explain());
  • Outras querys: remoção
    • Remover um usuário da coleção “users”
    • Remover todos os usuários
    • Remove uma coleção:
    • Remove uma database:
    $col->remove(); $col = $db->selectCollection(“users”); $query = array(“nome” => “Joaozinho”); $col->remove($query); $db->dropCollection(“users”); $db->drop();
  • Outras querys: Erros
    • No MongoDB, operações de escrita (insert / update / delete) não bloqueam (“fire and forget”) e sempre retornam true. Para verificar se uma operação deu erro, deve-se usar método lastError()
    $doc = array(“_id” => 1); $col = $db->selectCollection(“error”); $col->insert($doc); if($error = $conn_mongodb->lastError()) { echo "Error: "; var_dump($error); }
  • Indo além
    • No momento, mongodb só pode em hosts dedicados / VPS
    • Desenvolvedores estão propondo suporte em hosts compartilhados
    • Documentação da extensão mongophp:
      • www.php.net/mongodb
    • Documentação oficial é bem completa:
      • www.mongodb.com
    • Lista de discussão com participação ativa e prestativa dos desenvolvedores:
      • http://groups.google.com/group/mongodb-user
  • Perguntas?