Nie ma NULLi!
Nie ma dat
A jak potrzebuję?
A po co Ci?
Do przechowywania? - long
Do wyszukiwania? - będzie później
{
"color":"blue"
}
Properta
Typy wartościowe
Node
Typy referencyjne
Prosta zasada:
Chcę po tym szukać
Node
Chcę to zwracać
To po co to przechowujesz?
Properta
Statystyki:
- 10 nodów Color
- 1.001.000 nodów Node
- 1.001.010 nodów
- 1.001.010 relacji
MATCH (c:Color {name:"blue"})<--(n) RETURN count(n)
MATCH (n:Node {color:"blue"}) RETURN count(n)
5975ms
118 ms
MATCH (a:Person)-[:IS_MARIED]-(b:Person)
- Filtracja po czasie/typie
- Dodanie propert filtrujących
- Dodanie wag dla relacji
- Sharding z utrzymaniem kopii noda
- Własny resolver relacji
Serwis do wyszukiwania biletów lotniczych
Chcemy móc zawężać wyniki po linii lotniczej
Wprowadzamy pośrednie wierzchołki
Pole określające kolejność
Listy
MATCH (timeline:Timeline{name:'timeline-1'})
-[:YEAR]->(y)
-[:MONTH]->(m)
-[:DAY]->(d)<-[:OCCURRED]-(n)
WHERE (y.value > {startYear} AND y.value < {endYear})
OR ({startYear} = {endYear})
OR (y.value = {startYear}
AND ((m.value > {startMonth})
OR (m.value = {startMonth}
AND d.value >= {startDay})
)
)
OR (y.value = {endYear}
AND ((m.value < {endMonth})
OR (m.value = {endMonth}
AND d.value <= {endDay})
)
)
RETURN n.name, (d.value + "-" + m.value + "-" + y.value) AS date;
MATCH
- określa ścieżkę
WHERE
- filtruje wyniki
RETURN
- zwraca wyniki
WITH
- łączy zapytania
(n:Node)
- zmienna typu node
[r:RELATION]
- zmienna typu relacja
p=(:Node)-[:LIKES]->(:Node1)
- zmienna typu ścieżki
{ name:'value' }
- property
()
- node
[]
- relacja
:TYPE:LABEL
- określa typ/label
MATCH (n)-[r]->(m)
RETURN n,r,m
MATCH (n:User)-[r:Likes]->(m:Movie)
RETURN n,r,m
MATCH (n:User)-[r:Likes]->(m:Movie)
, (m:Movie)-[:DIRECTED_BY]->(p:Person {name:'Béla Tarr'})
RETURN n,r,m,p
MATCH (n:User) RETURN n
MATCH (n) RETURN n
Definiuje ścieżkę/ścieżki
Filtruje ścieżkę
MATCH (n:User)-->(m) RETURN n
MATCH (n:User)-[:LIKES]->(m) RETURN n
MATCH (n:User)-[r:Likes]->(m:Movie)
, (m:Movie)-[:DIRECTED_BY]->(p:Person {name:'Béla Tarr'})
RETURN n,r,m,p
MATCH (u:User)-[r:RATED]->(m:Movie)
OPTIONAL MATCH (u)-[FRIEND]->(p:Person)-[ACTS_IN]->(m)
RETURN u.login,m.title,p.name
MATCH (u:User)-[r:RATED]->(m:Movie)
OPTIONAL MATCH (u)-[FRIEND]->(p:Person)-[ACTS_IN]->(m)
-[DIRECTED]->(d:Director)
RETURN u.login,m.title,p.name,d.name
MATCH (u:User)-[r:RATED]->(m:Movie)
OPTIONAL MATCH (u)-[FRIEND]->(p:Person)-[ACTS_IN]->(m)
OPTIONAL MATCH (m)-[DIRECTED]->(d:Director)
RETURN u.login,m.title,p.name,d.name
Dopasowanie całej ścieżki
Dopasowanie osobnych ścieżek
UNION
UNION ALL
MATCH (u:User)
RETURN u.login as name
UNION
MATCH (p:Person)
RETURN p.name as name
MATCH (u:User)
RETURN u.login as name
UNION ALL
MATCH (p:Person)
RETURN p.name as name
MATCH (n:User)-[:RATED]->(m:Movie)
WITH n,count(m) as ratedMovies
ORDER BY ratedMovies DESC
MATCH (n:User)-[:FRIEND]->(f:Person)
WITH n,ratedMovies,count(f) as friendedPeople
RETURN n.login,ratedMovies,friendedPeople
- Agregacja
- Pipowanie zapytań
LIMIT
MATCH (p:Person)
RETURN p
LIMIT p
SKIP
MATCH (p:Person)
RETURN p
SKIP 10
LIMIT 20
REMOVE - do Label
MATCH (p:Director)
WHERE not (p)-[:DIRECTED]->(:Movie)
REMOVE p:Director
DELETE - do nodów
MATCH (p:Director)
WHERE not (p)-[:DIRECTED]->(:Movie)
DELETE p
MATCH p=(d:User)-[*]-(f:Director)
RETURN nodes(p)
Limit 20
nodes
MATCH p=(d:User)-[*]-(f:Director)
RETURN length(p)
Limit 20
length
MATCH p=(d:User)-[*]-(f:Director)
RETURN relationships(p)
Limit 20
relationships
MATCH (b:Book)
WHERE ANY (tag IN b.tags WHERE tag IN ['nosql','neo4j'])
RETURN t.name,b.tags
Operatory: ANY, ALL, NONE, SINGLE
MATCH (b:Book)
WHERE ANY (tag IN b.tags WHERE tag = 'nosql')
AND NONE (tag IN b.tags WHERE tag = 'neo4j')
RETURN b.title, b.tags
MATCH (p:Project)
FOREACH (t IN p.tag |
MERGE (tagNode:Tag{value:t})
MERGE (project)-[:TAG]->(tagNode))
REMOVE p.tag
Pipowanie operacji na kolekcjach
RETURN FILTER (x IN [1,2,3,4] WHERE x%2=0)
Filtracja elementów zwracanych kolekcji
MATCH p= (e)-[*]->(a:Movie)
WITH p
LIMIT 10
RETURN FILTER (node IN nodes(p) WHERE node:Person)
MATCH p=shortestPath( (a:User)-[*]-(b:Director) )
FOREACH (n IN nodes(p) | CREATE (n)-[:USER_TO_DIRECTOR]->(b))
MATCH (p:Person)-[:RATED]->(m:Movie)
RETURN p.name,collect(m.title)
COLLECT - zamiana w tablicę
MATCH path=(p:Person)-[:RATED]->(m:Movie)
RETURN EXTRACT(node in nodes(path) | Labels(node))
EXTRACT - zamiana w elementy
MATCH (n:User)-[r:Likes]->(m:Movie {MovieName:{name}})
RETURN n,r,m
MATCH (n:User)-[r:{Type}]->(m:Movie)
RETURN n,r,m
Nie OK:
OK:
MATCH p= (e)-[*]->(a:Movie)
WITH p
LIMIT 10
RETURN REDUCE (path="START", i IN nodes(p) | path +"->"+head(labels(i))) as Text
RETURN REDUCE (total = 0, i in [1,2,3] | total + i)
http://neo4j.com/docs/cypher-refcard/current/
APOC(Awesome Procedures On Cypher)
CALL apoc.help("apoc")
- Uzupełnienie Cyphera
- Funkcje Javowe
- 194 funkcje
- Obsługę indeksów
- Tworzenie meta grafów
- Eksport/import z jsona (bazy relacyjne,CSV,JSON, HTTP)
- Integracja z Elastic
- Monitoring
- Joby
- Operacje Gisowe
- Metody kolekcji
- Stemming
- Daty!
- Dodatkowe algorytmy grafowe
g.V().has("name","gremlin")
.out("knows")
.values("name")
Tworzenie AST
Normalizacja AST
Błędy składniowe
Błędy w typach
Tworzenie wielu planów logicznych wykonania zapytania
Szacowanie kosztów i zysków operacji logicznych
Dobór indeksów
Podobny do wybranego planu logicznego
Zawiera natywne operatory
EXPLAIN - szacuje, nie wykonuje
PROFILE - szacuje, wykonuje
Prefixy do komend
Abstrakcyjna jednostka operacji db hit
- All nodes scan
- Label scan
Operatory:
- Node index seek
- Node index scan
MATCH (movie {title:"The Matrix"})
RETURN movie
MATCH (movie:Movie {title:"The Matrix"})
RETURN movie
CREATE INDEX ON :Movie(title)
CREATE INDEX ON :Person(name)
Wykorzystywane tylko do znalezienia startowego punktu
MATCH (movie {title:"The Matrix"})
RETURN movie
MATCH (movie:Movie {title:"The Matrix"})
RETURN movie
MATCH (a:Person {name:"Tom Hanks"})-[:ACTS_IN]->
()<-[:ACTS_IN]-(b:Person {name:"Meg Ryan"})
RETURN count(*)
MATCH (a:Person {name:"Tom Hanks"})-[:ACTS_IN]->
()<-[:ACTS_IN]-(b:Person {name:"Meg Ryan"})
USING INDEX a:Person(name)
USING INDEX b:Person(name)
RETURN count(*)
Średnio:
Lepiej:
MATCH (a:Person {name:"Tom Hanks"})-[:ACTS_IN]->
(m1)<-[:ACTS_IN]-(coActor)-[:ACTS_IN]->(m2)
RETURN distinct m2.title
MATCH (a:Person {name:"Tom Hanks"})-[:ACTS_IN]->
(m1)<-[:ACTS_IN]-(coActor)
WITH DISTINCT coActor
MATCH (coActor)-[:ACTS_IN]->(m2)
RETURN distinct m2.title
Średnio:
Lepiej:
MATCH (a:Actor)-->(m:Movie:Comedy)
RETURN count(distinct a)
MATCH (a:Actor)-->(m:Movie:Comedy)
USING SCAN m:Comedy
RETURN count(distinct a)
MATCH (a:Actor),(m:Movie)
RETURN count(a),count(m)
MATCH (a:Actor)
WITH count(a) as actorCount
MATCH (m:Movie)
RETURN actorCount,count(m)
Bardzo źle:
Dobrze:
Warunki w MATCH, nie w WHERE
Zawężanie startowych nodów
Indeksy dla startowych nodów
Agregaty i distinct - z uwagą
Określanie kierunku relacji.
Czyli -[]-> a nie -[]-
Lepiej wiele MATCH zamiast jednego
:play sysinfo
Co to są memory mapped files?
neostore.nodestore.db.mapped_memory
neostore.relationshipstore.db.mapped_memory
neostore.propertystore.db.mapped_memory
neostore.propertystore.db.strings.mapped_memory
neostore.propertystore.db.arrays.mapped_memory
Pamiętaj o stosie Javy!
Co to jest block size?
label_block_size
array_block_size
string_block_size
Czemu mam się tym przejmować?
node_auto_indexing
Auto indeksacja
Zwiększyć ulimit
Ustawić use_memory_mapped_buffers na true
GC:
- Copying collector (default)
- -XX:+UseConcMarkSweepGC
- -XX:+UseParallelGC (dla stosu >10GB)
Java options:
- -server flag
- Xmx - max pamięci
- Xms - min pamięci
Reszta: http://www.oracle.com/technetwork/articles/java/vmoptions-jsp-140102.html
jvmtop(https://github.com/patric-r/jvmtop)
Możliwość monitorowania jednego procesu
(jvmtop.bat <pid>)
jvisualvm(https://visualvm.java.net)
Trochę historii
Porównanie
Co | Embedded | Server |
---|---|---|
1 Tx per node (1,000,000 x 1) | 168,815 ms (5,952 nodes/sek) |
2,380,140 ms (420 nodes/sek) |
1 Tx (1 x 1,000,000) | 25,654 ms (40,000 nodes/sek) |
- |
(20 x 50,000) | 16,081 ms (62,500 nodes/sek) |
148,357 ms (6756 nodes/sek) |
REST - Transakcja (domyślnie)
Transakcja - wątek
Bolt
Pluginy
Deployment przez umieszczenie w katalogu
Widoczny poprzez url
Dziedziczenie po SeverPlugin
Ma dostęp co corowego API
(jak w embeded mode)
Deployment przez umieszczenie w katalogu
+ wpis w configu
Widoczny poprzez url
Nie musimy po niczym dziedziczyć
Dostaje bazę jako dependency
Template (https://goo.gl/JZylMb)
Co | Liczba operacji | curl | Klient |
---|---|---|---|
REST API | 602 | 5303ms | 917ms |
Cypher | 1 | 45ms | 32ms |
Server plugin | 1 | 20ms | 16ms |
Unmanaged extension | 1 | 20ms | 18ms |
Możliwość określenia typu trawersacji
- Breadth first (domyślny)
- Depth first
- A*,....
Customowy trawerser
Customowy resolver krawędzi
Wywołania funkcji
Manualne (Lucene)
Auto indexes
Schema indexes
Pierwsze indeksy w Neo4j
Na bazie Lucene
Zarządzane całkowicie przez API
Nie ma update
Nie mają pojęcia o labelach
Mogą być full textowe
Mogą operować na wielu propertach
Można przekazać dodatkowe opcje
(http://goo.gl/haLQpp)
Mogą indeksować relacje
Wywołanie w Cypher:
Wywoływanie w cypher ze składnią Lucene:
Zarządzanie w Cypher poprzez:
start n=node:users("name:John Johnson")
return n
start n=node:users(name="John Johnson")
return n
call apoc.index.*
Od wersji 1.4
Pod spodem to manualny indeks
Mogą dotyczyć nodów i relacji
Włączenie w configu:
- node_auto_indexing=true
- relationship_auto_indexing=true
Jeden dla całej bazy
Indeks jest dla property
Asynchroniczne
Automatyczne
Mogą mieć tylko jedno pole z labela
Tworzenie:
CREATE INDEX ON :Person(name);
Niszczenie:
DELETE INDEX ON :Person(name);
Tworzenie:
CREATE INDEX ON :Person(name);
Niszczenie:
DELETE INDEX ON :Person(name);
Tworzenie constrainów
CREATE Constraint on (node:Person)
ASSERT node.name IS Unique
Usuwanie
DROP Constraint on (node:Person)
ASSERT node.Name IS UNIQUE
schema - listuje indeksy
schema -l :Person -p INDEX_NAME - stan indexu INDEX_NAME
opcje:
- l - wszystkie indeksy na labelu
- p - indeksy na propercie
- v - błędy jeżeli indeks jest w błędnym stanie
CALL apoc.index.list()
Lista indeksów:
neo4j-shell (od 3.0 tylko Linux)
Community Edition
- offline (kopiowanie plików ręcznie)
Enterprise Edition
- online (bez wyłączania bazy)
- full
- incremental
Klastrowanie
Master + many slaves
Master - read/write
Slave - read
PAXOS - wyłanianie mastera
Slave - pełna kopia
Asynchroniczna replikacja (by default)
Ustawienia:
- ha.pull_interval - jak często slave pyta mastera (sek)
- ha.tx_push_factor - ilość slavów potwierdzających commit zanim master wyśle commit (0 - asynchronicznie)
- ha.tx_push_strategy - fixed/round robin. Wybór slavóow do których wypychane są dane.
http://volkanpaksoy.com/archive/2015/02/19/visual-tools-for-neo4j/
Dema
Książki
Program dla startupów