Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/suissa/levelgraph-tutorial
Tutorial sobre Levelgraph
https://github.com/suissa/levelgraph-tutorial
Last synced: 24 days ago
JSON representation
Tutorial sobre Levelgraph
- Host: GitHub
- URL: https://github.com/suissa/levelgraph-tutorial
- Owner: suissa
- Created: 2014-12-14T22:59:48.000Z (about 10 years ago)
- Default Branch: master
- Last Pushed: 2014-12-15T02:24:41.000Z (about 10 years ago)
- Last Synced: 2024-10-30T01:46:30.691Z (2 months ago)
- Size: 129 KB
- Stars: 15
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
#Levelgraph
##O que é?
É um banco de dados de grafos diferentemente dos outros bancos de grafos ele feito em cima do rapidíssimo [LevelDB](http://code.google.com/p/leveldb/), você pode usar ele dentro da sua aplicação Node.js ou no navegador!
![](https://cldup.com/wvRSezLXzR.png)
A imagem a cima é um exemplo de um grafo onde temos:
- A: sujeito
- B: objeto
- C: predicado**A** é a entidade de onde parte uma conexão.
**B** é a entidade que recebe a conexão.
**C** é a conexão em si.> Suissa(A) ensina(C) Javscript(B).
> João(A) estuda(C) Javascript(B).Isso se chama **tripla**. caso queira saber mais sobre [Grafos entre aqui](http://pt.wikipedia.org/wiki/Teoria_dos_grafos).
##Por que usar?
Um banco de dados de grafos facilita nossa vida quando precisamos conectar entidades do nosso sistema e nesse caso o Levelgraph é uma ótima escolha já que podemos utilizá-lo tanto no navegador como no servidor e é feito com Node.js por isso facilmente integrável.
Por exemplo quem usa MongoDb sabe que é muito custoso separar em várias coleções pois ele não possui JOIN, o cenário ideal seria deixar a modelagem real no MongoDB e usar o Levelgraph para criar a rede de conexões das entidades e que ele seja usado para esse tipo de busca.
Pegando nosso exemplo acima, vamos ver algumas buscas que podemos fazer em um banco de grafos:
> Busque todas pessoas que estudam Javascript
> Busque todas pessoas que estudam Javascript ensinado por Suissa
> Busque todas pessoas que ensinam JavascriptIsso apenas com uma conexão, imagine com diversas.
##Como usar?
Vamos começar instalando ele localmente na nossa aplicação.
```
npm install levelgraph --save
```Ou para usar no navegador você pode baixar o [levelgraph.min.js](https://github.com/mcollina/levelgraph/blob/master/build/levelgraph.min.js).
Para iniciar uma database é bem simples:
```
var levelgraph = require("levelgraph"); // não precisa no navegador
var db = levelgraph("yourdb");
```###Inserindo
Inserir uma conexão(tripla) é super simples, para isso usaremos a função `put`:
```
db.put(tripla, callback);
```Como vemos no exemplo abaixo:
```
var triple = { sujeito: "a", predicado: "b", objeto: "c" };db.put(triple, function(err) {
if(err) console.log('ERROR: ', err);console.log('INSERIU');
db.get({ sujeito: "a" }, function(err, list) {
console.log(list);
});
});
```E quando rodamos no terminal recebemos a seguinte saída:
![log do objeto inserido](https://cldup.com/Wx8e7yJ8q0.png)
####Propriedades
Podemos adicionar mais propriedades na tripla dessa forma:
```
var triple =
{ sujeito: 'a'
, predicado: 'b'
, objeto: 'c'
, novaPropriedade: 'teste'
};db.put(triple, function(err) {
if(err) console.log('ERROR: ', err);console.log('INSERIU');
db.get({ sujeito: 'a' }, function(err, list) {
console.log(list);
});
});```
![](https://cldup.com/to9uAItuB0.png)
Além disso podemos criar objetos no sujeito, predicado e/ou objeto, como vemos abaixo:
```
var triple =
{ sujeito: {name: 'Suissa'}
, predicado: 'ensina'
, objeto: {linguagem: 'Javascript'}
};db.put(triple, function(err) {
if(err) console.log('ERROR: ', err);console.log('INSERIU');
db.get({ sujeito: {name: 'Suissa'} }, function(err, list) {
console.log(list);
});
});
```![](https://cldup.com/EeNY1xA7v0.png)
###Consultando
Bom como vimos no exemplo anterior usamos a função `get`:
```
db.get({ subject: "a" }, function(err, list) {
// Faz algo
});
```Vamos inserir várias triplas e depois listá-las:
```
var triples =
[ { subject: "Suissa"
, predicate: "ensina"
, object: "Javascript"
}
, { subject: "Odin"
, predicate: "estuda"
, object: "Javascript"
}
, { subject: "Thor"
, predicate: "estuda"
, object: "Javascript"
}
, { subject: "Loki"
, predicate: "estuda"
, object: "Javascript"
}
, { subject: "Heimdall"
, predicate: "estuda"
, object: "PHP"
}
, { subject: "Frey"
, predicate: "estuda"
, object: "PHP"
}
, { subject: "Galvão"
, predicate: "ensina"
, object: "PHP"
}
]
;db.put(triples, function(err) {
if(err) console.log('ERROR: ', err);
console.log('INSERIU');
db.get({}, function(err, list) {
console.log(list);
});
});
```![](https://cldup.com/QeaXDKYqSV.png)
Vamos consultar quais são nossos professores:
```
db.get({predicate: "ensina"}, function(err, list) {
console.log(list);
});
```![Listagem dos professores](https://cldup.com/jUQd-yys3R.png)
E quais são nossos alunos:
```
db.get({predicate: "estuda"}, function(err, list) {
console.log(list);
});```
![Listagem dos alunos](https://cldup.com/T7CfIhSDaN.png)
Legal mas e como que eu posso buscar todos que estudam Javascript?
Tão simples quanto a busca anterior, só precisamos passar mais um atributo no objeto da query:
```
db.get({predicate: "estuda", object: "Javascript"}, function(err, list) {
console.log(list);
});
```![Listagem dos alunos que estudam Javascript](https://cldup.com/qw2_kPgVju.png)
###Streams
Ele também suporta streams, vamos ver um exemplo de como buscar os amigos entre uma pessoa e outra:
```
db.put([{
subject: "Suissa",
predicate: "segue",
object: "Galvão"
}, {
subject: "Galvão",
predicate: "segue",
object: "Suissa"
}, {
subject: "Galvão",
predicate: "segue",
object: "Eminetto"
}, {
subject: "Piaz",
predicate: "segue",
object: "Suissa"
}, {
subject: "Piaz",
predicate: "segue",
object: "Eminetto"
}, {
subject: "Eminetto",
predicate: "segue",
object: "Duodraco"
}], function () {var stream = db.searchStream([{
subject: "Suissa",
predicate: "friend",
object: db.v("x")
}, {
subject: db.v("x"),
predicate: "friend",
object: db.v("y")
}, {
subject: db.v("y"),
predicate: "friend",
object: "Duodraco"
}]);stream.on("data", function(data) {
console.log('Caminho percorrido: ', data);
});
});
```Para entendermos quem segue quem fiz esse exemplo visual:
![](https://cldup.com/VstqbL8F0Q.png)
Essa busca está procurando qual o caminho que preciso percorrer entre quem **Suissa** segue até chegar em quem segue o **Duodraco**, qualuqer semelhança com aquela feature *Pessoas que você possa conhecer* não é mera coincidência.
Rodando essa busca no terminal temos:
![](https://cldup.com/EW6eY_Gt7K.png)
###Caminhando
Essa API de caminhada é baseada no [Gremlin](http://markorodriguez.com/2011/06/15/graph-pattern-matching-with-gremlin-1-1/).
Para termos maior facilidade nas buscas que retornam um caminho podemos usar as funções `archIn` e `archOut`.
Re-usando aquele exemplo do ensina/estuda Javascript, para sabermos todas pessoas que estudam Javascript basta fazermos:
```
db.nav("Javascript")
.archIn("estuda")
.solutions(function(err, results) {
// prints:
// [ { x0: 'Loki' }, { x0: 'Odin' }, { x0: 'Thor' } ]
console.log(results);
});
```Mas vamos voltar ao nosso exemplo dos seguidores, a busca mais simples é achar as pessoas que seguem o **Suissa**:
```
db.nav("Suissa")
.archIn("segue")
.solutions(function(err, results) {
// prints:
// [ { x0: 'Galvão' }, { x0: 'Piaz' } ]
console.log(results);
});
```Então a função `archIn` é a responsável pela predicado que chega na entidade setada em `db.nav()`.
Logo a função `archOut` ´a responsável pelo predicado que sai da entidade, então vamos buscar quem o **Suissa** segue:
```
db.nav("Suissa")
.archOut("segue")
.solutions(function(err, results) {
// prints:
// [ { x0: 'Galvão' } ]
console.log(results);
});
```E se quisermos saber os seguidores dos seguidores do **Suissa**?
Muito fácil, como visto abaixo:
```
db.nav("Suissa")
.archOut("segue")
.archOut("segue")
.solutions(function(err, results) {
// prints:
// [ { x0: 'Galvão', x1: 'Eminetto' },
// { x0: 'Galvão', x1: 'Suissa' } ]
console.log(results);
});
```Só precisamos adicionar outra chamada para `.archOut("segue")` e assim sucessivamente para aumentar o grau da busca.
Ai você se pergunta: **o que que acontece se eu adicionar um archIn ali no final?**
Ótima pergunta! Vamos ver então:
```
db.nav("Suissa")
.archOut("segue")
.archOut("segue")
.archIn("segue")
.solutions(function(err, results) {
// prints:
// [ { x0: 'Galvão', x1: 'Eminetto', x2: 'Galvão' },
// { x0: 'Galvão', x1: 'Eminetto', x2: 'Piaz' },
// { x0: 'Galvão', x1: 'Suissa', x2: 'Galvão' },
// { x0: 'Galvão', x1: 'Suissa', x2: 'Piaz' } ]
console.log(results);
});
```Nesse caso nossa busca é o seguinte:
- inicie em Suissa
- busque um objeto que ele se conecte via "segue" // Galvão
- busque um objeto que ele se conecte via "segue" // Eminetto
- busque um objeto que ele receba conexão via "segue" // Galvão, PiazDestrinchando oresultado um pouco mais:
```
{ x0: 'Galvão', x1: 'Eminetto', x2: 'Galvão' }
```> Suissa segue Galvão, Galvão segue Eminetto, Galvão é seguido por Suissa
```
{ x0: 'Galvão', x1: 'Eminetto', x2: 'Piaz' }
```> Suissa segue Galvão, Galvão segue Eminetto, Eminetto é seguido por Piaz
```
{ x0: 'Galvão', x1: 'Suissa', x2: 'Galvão' }
```> Suissa segue Galvão, Galvão segue Suissa, Suissa é seguido por Galvão
```
{ x0: 'Galvão', x1: 'Suissa', x2: 'Piaz' }
```> Suissa segue Galvão, Galvão segue Suissa, Suissa é seguido por Piaz
Creio que deu para notar que ele vai caminhando e aplicando a busca, como vimos na última busca que é um `archIn` nosso *"caminhador"* para na entidada achada no último `archOut` e executa o `archIn` por isso achando por quem essa entidade **é seguido**.