NoSQL: Bancos de dados orientados à grafos

Model: Graph Store (Neo4j)

História

Grafos são um conceito extremamente antigo.
A primeira menção a isso remonta a Leonhard Euler em 1736, de armazenamento e visualização de dados e suas relações.
Criado em 2007, tornou-se rapidamente o banco mais usado no seguimento, e também um dos mais rápidos (Grafo Nativo).
License: Source code: GPLv3 and AGPLv3 e Binaries: Freemium registerware.
Scheme Free: Nada precisa ser pré-definido. Tudo é identificado em tempo de criação do objeto.
Nós não necessariamente precisam ter as mesmas propriedades.

Introdução

São estruturas matemáticas composta de duas partes básicas, nós e arestas (ou vértices).
Nó: Representa o dado, uma entidade do sistema, por exemplo, um usuário, um role, um scope.
Arestas ou Vértices: São os relacionamentos em si.
Cypher é a linguagem oficial de consultas.

NoSQL Graph Image

Tipos de Grafos

Grafo Nativo
Fisicamente na memória, os nós e relacionamentos apontam uns para os outros. Isso cria o que é chamado de adjacência livre de índices (index-free adjacency) e, desta forma, os sistemas de grafos nativos, podem fazer uma query através de travessias de grafos, pulando de um endereço para outro na memória de forma absurdamente rápida. Na verdade, o chamado pointer hoping é a forma mais rápida de um computador acessar um dado relacionado. Você pode ver mais detalhes sobre este tema neste excelente artigo

Grafo Não Nativo
Se apoiam sobre bancos de dados relacionais ou não relacionas já existentes para que possam gerenciar seus relacionamentos. Em outras palavras, eles tem uma representação de um grafo em forma de tabelas ou documentos, o que os torna cerca de 1000x mais lento do que um grafo nativo, somente pelo fato de que a maioria dos dados que precisamos acessar não está diretamente carregado na memória.

Usabilidade

Comum em detecção de fraudes, mecanismos de recomendação, redes sociais, sistemas de arquivos, games, etc.
logística, veja o problema do caixeiro viajante.
Internet, que, se pensarmos bem, é um grafo gigante e roteadores que se utilizam de algoritmos de menor caminho (como Dijkstra) para encontrar o menor caminho entre outros roteadores até o IP de destino.

Exemplos

Criação de uma estrutura de registros que compõem os dados de uma rede social utilizando um sandbox do Neo4j.
NÓS e RELACIONAMENTOS podem ter propriedades e labels.
As labels podem ser criadas, atualizadas ou removidas a qualquer momento, na criação ou atualização do NÓ ou RELACIONAMENTO.

Consulta de NÓ

                                // Exemplo sem condição (Todos)
                                MATCH (var) RETURN var;

                                // Exemplo com condição
                                MATCH (var:Client) WHERE var.name = 'Heviane' RETURN var;
                            
MATCH é o comando para buscar o NÓ, sempre será usado em conjunto nas operações em NÓS já existentes.
var é a variável atribuída a label Client que e que vai receber o resultado da consulta.

Criação de NÓ

                                CREATE (:Client {name: 'Heviane', age: 39, hobbies: ['Caminhada', 'Musculação']});
                            
Label "Client" é opcional, é o que vem depois dos dois pontos (:).
Node é o conjunto inteiro do dado, é o dado em si.
name, age, hobbies são as propriedades do dado.

Criação de NÓ com relacionamento

                                CREATE (:Client {name: 'Maria', age: 57, hobbies: ['Jardinagem', 'Cozinhar']}) 
                                - [:Bloqueado] -> (:Client {name: 'Nina', hobbies: ['Carpintaria']});
                            
Colchetes [] definem uma relacionamento.
Seta -> para indicar a direção do relacionamento (vértice).
Relacionamentos podem ou não ter uma label, que é definida dentro dos colchetes
O comando vai acima vai criar: Um NÓ -> Um Relacionamento -> Um NÓ. (O comando CREATE não precisa ser replicado)

Criação de Relacionamento entre NÓS já existentes

                                // Heviane vai bloquear a Maria.
                                MATCH (Heviane:Client{name: 'Heviane'}),(Maria:Client{name: 'Maria'})
                                CREATE (Heviane)-[:Bloqueado]->(relMaria);

                                // Heviane vai desbloquear a Maria.
                                MATCH (Heviane:Client{name: 'Heviane'})-[rel:Bloqueado]-() DELETE rel;
                            
Parenteses vazio () é um Nó anonimo, usado para deletar todos.

Exclusão de NÓ

                                // Atribuindo o nó a variável Heviane
                                MATCH (Heviane:Client{name: 'Heviane'}) DELETE Heviane;
                            

Atualização de propriedades de NÓ

                                // Atualizando a propriedade age
                                MATCH(nina:Client{name: 'Nina'}) SET nina.age = nina.age + 1;

                                // Atualizando a propriedade hobbies
                                MATCH(nina:Client{name: 'Nina'}) SET nina.hobbies = ['Caminhada'];
                            
O fluxo de atualização é o mesmo para NÓS e RELACIONAMENTOS, o que for atribuído a variável.

Atualização de labels de NÓ

                                MATCH(nina:Client{name: 'Nina'}) SET nina:Client_Premium;
                            

References