Brincando com bancos do tipo Grafos com Java

 

 

   Os bancos NoSQL estão cada vez mais populares e em diversos segmentos, dentre os seus tipos definidos está o banco do tipo grafos. O banco de grafos tem uma estrutura consideravelmente diferente se comparado aos bancos relacionais, dentre os maiores cases de uso estão as recomendações em sistemas de redes sociais, por exemplo, facebook e linkedin compras e entretenimento inclusive em setores mais conservadores como o financeiro que está o utilizando com objetivo de evitar fraudes bancárias. O objetivo desse artigo é explorar os conceitos dos grafos e como utilizar de maneira bastante simples com Java.

 

Estrutura do Banco do Grafo

O Banco de grafos é composto, basicamente por três elementos:

  • Property: É o menor elemento dentro do grafo, ele é uma tupla, ou seja, é composta por uma chave e valor em que a chave é o nome e o valor é a informação em si.
  • Vertex: Seria semelhante a uma tabela num banco relacional, ele é composto por uma ou mais propriedades.
  • Edge: é o elemento que representa a relação entre os Vertex, seria um elemento de relação comparado com um banco relacionado, porém, esse elemento também é composto por propriedades. O fato do Edge ter propriedades traz uma nova dimensão.

O sentido do grafo é algo muito importante, afinal, o fato de você conhecer uma pessoa não significa que ela te conheça. Assim, de uma maneira geral podemos pensar da seguinte forma:

  • Out: Vertex → action → Vertex o “out” é o sentido da ação, ou seja, eu conheço o homem de ferro, assim: Me → knows → Iron man.
  • In: Vertex ← passive verb ← o “in” é o sentido oposto, ou seja, da reação essa operação é “automaticamente” salva quando você realizar uma operação de ação, por exemplo, o homem de ferro é conhecido por me, assim: Iron man → is known → me.

Provedores de banco de dados

 

O banco de Grafos são compostos por diversos provedores, sendo o mais popular o Neo4J. Assim temos:

Certamente uns dos grandes problemas no grande número de servidores de grafos está no grande número de APIs, uma vez que cada banco tem a sua própria API, por exemplo, faz com que seja muito difícil aprender cada uma delas, sem falar no problema do lock-in, ou seja, caso você opte por um banco de dados caso faça a mudança você perderá toda a sua camada de persistência, sem falar na curva de aprendizado uma vez que para cada novo banco será necessário aprender uma nova API.

 

TinkerPop criando um padrão para os bancos de grafos

Com o objetivo de evitar os problemas mencionados anteriormente, nasceu o TinkerPop. O TinkerPop é um projeto da Apache Foundation que cria uma API comum para realizar as operações de bancos de dados além das Queries. Com o TinkerPop é muito simples realizar queries e sem se preocupar com o Vendor. Atualmente o TinkerPop suporta mais de 30 bancos de dados do tipo grafo.

 

Exemplos que demonstram a vantagem do Grafos em relação ao banco relacional

 

Imagine uma simples estrutura hierárquica, por exemplo, uma cadeia alimentar uma hierarquia empresarial. Como mostra a figura abaixo:

Com o intuito de realizar a comparação, como você percorreria essa cadeia num banco relacional?

Possivelmente, teria que ter uma nova tabela para fazer essa lógica ou coisa semelhante. Então com o TinkerPop você precisaria executar uma query como essa:

g.V().repeat(out("eats")).times(3);//para percorrer a lista três vezes 
g.V().repeat(out("eats")) .until(has("name", "grass"));//para percorrer até achar um Vertez com o nome “grass”.

Simples não?

 

Tá e as minhas entidades?

TinkerPop tem suporte ao Java, com a sua própria API, no entanto, no nosso dia a dia nós trabalhamos com entidades, por exemplo, livros, pessoas dentre outras coisas e para realizar tal comunicação é necessário fazer um parse para cada entidade.

JNoSQL

O JNoSQL é uma ferramenta cujo o objetivo é facilitar a comunicação entre os bancos não relacionais e suas entidades Java, para isso, ele consta com uma API simples, porém, extensível, assim mesmo com uma API padrão é possível extende-la para usar um recurso específico de um banco de dados. O JNoSQL conta com duas sub APIs uma para comunicação, semelhante ao JDBC, e uma para mapeamento, semelhante ao JPA.

JNoSQL e Grafos

 

Para realizar tal integração o JNoSQL utiliza sua camada de mapeamento, aka Artemis, e realiza um parser para o TinkerPop. Assim, para retratar esse grafo no mundo JNoSQL.

1) Realizar o mapeamento das classes Pessoa e livro

@Entity
public class Book {

 

@Id
private Long id;

@Column
private String name;

//getter and setter
}

@Entity
public class Person {

@Id
private Long id;

@Column
private String name;

@Column
private int age;

@Column
private String occupation;

@Column
private Double salary;

//getter and setter
}

 

Injetar a classe GraphTemplate

 

@Inject
private GraphTemplate graph;

//caso você esteja utilizando CDI 2.0 no SE
GraphTemplate graph = container.select(GraphTemplate.class).get();

 

Salvar as entidades

 

Person poliana = Person.builder().withName("Poliana").withAge(25).build();

Book shack = Book.builder().withAge(2007).withName("The Shack").build();

graphTemplate.insert(poliana);
graphTemplate.insert(shack);

 

Criar a relação [Edge]

EdgeEntity<Person, Book> reads = graphTemplate.edge(poliana, "reads", shack);
reads.add("where", "Brazil");

Pronto, você fez sua primeira operação com um grafo.

 

Um caso prático com Grafo {Fazendo queries].

 

Imagine o seguinte cenário:

1) Trabalhamos para uma agência de marketing e queremos fazer uma campanha para um público específico que será:

 

  • Um engenheiro
  • Cujo salário seja maior que 3000
  • Tenha idade entre 20 e 25 anos

Para esse caso, seria simples fazer essa query tanto no banco relacional como no grafo, focando em grafos com o JNoSQL ficará da seguinte forma:

List<Person> developers = graph.getTraversalVertex()
.has("salary", gte(3_000D))
.has("age", between(20, 25))
.has("occupation", "Developer")
.<Person>stream().collect(toList());

 

2) Os amigos desse engenheiro

 

Uma vez definido o nosso target, o nosso engenheiro com características específicas, queremos também trazer seus amigos, afinal, eu mesmo não atendendo os requisitos posso indicar o produto para um amigo que também tenha essas características.

Fazer esse tipo de operação no banco relacional começa a ficar mais difícil, porém, no nosso caso será necessário apenas colocar uma condição, out(“knows”), uma vez que queremos todas as condições e queremos alguém que o engenheiro conheça.

List<Person> result = graph.getTraversalVertex()
.has("salary", gte(3_000D))
.has("age", between(20, 25))
.has("occupation", "Developer")
.out("knows");
3) A pessoa que o engenheiro ama

 

Nesse caso, queremos maior “profundidade” na pessoa que o engenheiro conhece, conhecer não é suficiente, é necessário que ele ama essa pessoa. Imagine que estamos fazendo uma campanha para os dias dos namorados. Nesse caso, utilizaremos um diferente item da query, outE(“knows”), semelhante ao out, porém, ele começa a mapear a relação, o Edge, assim dentro dessa relação eu quero que ele busque uma propriedade, nesse caso, o sentimento de amor.

 

List<Person> love = graph.getTraversalVertex()
.has("salary", gte(3_000D))
.has("age", between(20, 25))
.has("occupation", "Developer")
.outE("knows")
.has("feel", "love")
.bothV()
.<Person>stream()
.distinct()
.collect(toList());

 

 

Os exemplos completos se encontram aqui:

https://github.com/JNOSQL/artemis-demo/tree/master/artemis-demo-java-se

Como essa versão ela ainda está em snapshot é necessário adicionar esse repositório para realizar tests, para mais informações:

https://stackoverflow.com/questions/7715321/how-to-download-snapshot-version-from-maven-snapshot-repository

Com isso, fizemos uma rápida introdução dos bancos do tipo Grafo com Java. Como foi possível demonstrar, mesmo que de maneira bem superficial, é possível realizar diversas buscas que no mundo relacional dariam muito trabalho e demandaria muito tempo de uma maneira bem mais natural.

 

Referências:
Anúncios

Um comentário sobre “Brincando com bancos do tipo Grafos com Java

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s