Przejdź do treści

Trovares xGT

Dokumentacja: http://docs.trovares.com/v1.4/index.html

Ponowne połączenie

Importujemy biblioteki i tworzymy połączenie.

In [ ]:
import xgt
import getpass
import os
server = xgt.Connection(userid='kdmszkXX', credentials=getpass.getpass(), port=os.getuid()+20000)
print('Wersja klienta: {}'.format(xgt.__version__))
print('Wersja serwera: {}'.format(server.server_version))

Upewnijmy się, że żadna ramka nie istnieje na serwerze.

In [ ]:
def clear_all():
    [server.drop_frame(frame) for frame in server.get_edge_frames()]
    [server.drop_frame(frame) for frame in server.get_table_frames()]
    [server.drop_frame(frame) for frame in server.get_vertex_frames()]
    
clear_all()

Wczytajmy ponownie dane osób (social_network/persons_0_0.csv) oraz dane relacji "kto kogo lubi" (social_network/person_knows_person_0_0.csv).

In [ ]:
persons = server.create_vertex_frame(
        name='ldbc__persons',
        schema=[['creationDate', xgt.DATETIME], ['id', xgt.INT], ['firstName', xgt.TEXT], ['lastName', xgt.TEXT], ['gender', xgt.TEXT], ['birthday', xgt.DATE],
               ['locationIP', xgt.IPADDRESS], ['browserUsed', xgt.TEXT]],
        key='id')

person_knows_person = server.create_edge_frame(
    name="ldbc__person_knows_person",
    schema=[['creationDate', xgt.DATETIME], ['Person1.id', xgt.INT], ['Person2.id', xgt.INT]],
    source=persons,
    target=persons,
    source_key='Person1.id', 
    target_key='Person2.id')

persons.load("/home/kdmszkXX/workshop/social_network/person_0_0.csv", headerMode=xgt.HeaderMode.IGNORE)
person_knows_person.load("/home/kdmszkXX/workshop/social_network/person_knows_person_0_0.csv", headerMode=xgt.HeaderMode.IGNORE)

Sprawdźmy ile wierzchołków Person i krawędzi Person_knows_person wczytano.

In [ ]:
print("liczba wierzcholkow Persons: " + str(persons.num_vertices))
print("liczba krawedzi Person_knows_person: " + str(person_knows_person.num_edges))

Trovares Query Language - pierwsze podejście

Wszystkie krawędzie w Trovares xGT są skierowane, natomiast sama relacja person knows person jest "z natury" symetryczna (bo jeśli osoba A zna osobę B, to także B zna A). Wczytaliśmy na razie krawędzie "w jedną stronę", co nie oddaje pełnej istoty relacji person knows person. W związku z tym sami utwórzmy brakujące krawędzie "w drugą stronę".

Posłuży nam do tego następujące zapytanie w Trovares Query Language. Pierwsza linijka wyszuka wzorzec, w którym osoba1 jest wierzchołkiem źródłowym krawędzi zna, a osoba2 jest wierzchołkiem docelowym tej krawędzi. Druga linijka utworzy "odbicie lustrzane" znalezionej krawędzi, tzn. nową krawędź biegnącą w drugą stronę.

In [ ]:
query = """
MATCH (osoba1:ldbc__persons)-[zna:ldbc__person_knows_person]->(osoba2:ldbc__persons)
CREATE (osoba2)-[zna_w_druga_strone:ldbc__person_knows_person { creationDate: zna.creationDate }]->(osoba1)
"""

server.run_job(query)

Sprawdźmy, czy rzeczywiście zostały dodane nowe krawędzie.

In [ ]:
print("liczba wierzcholkow Persons: " + str(persons.num_vertices))
print("liczba krawedzi Person_knows_person: " + str(person_knows_person.num_edges))

Słowa kluczowe

Pełen spis słow kluczowych znajduje się na tej stronie: link.

Do słów kluczowych omawianych na tych warsztatach należą:

MATCH

Słowo kluczowe, od którego zaczynamy zapytanie. Po nim musi nastąpić jedna lub kilka (połączonych ,) sekwencji (w1:ramka_wierzcholkow1)-[k:ramka_krawedzi]->(w2:ramka_wierzcholkow2), gdzie:

  • w1, k i w2 wiążą w znalezionym wzorcu wierzchołki i krawędzie
  • ramka_wierzcholkow1, ramka_krawedzi i ramka_wierzcholkow2 to nazwy ramek z których wierzchołki i krawędzie muszą pochodzić,
  • - oznacza, że występujący po lewej stronie wierzchołek to źródło krawędzi,
  • -> oznacza, że występujący po prawej stronie wierzchołek to cel krawędzi.

CREATE

Tworzy krawędź bądź wierzchołek.

WHERE

Definiuje ograniczenia na atrybuty wierzchołków i krawędzi.

RETURN [... as ...]

Zwraca konkretne wartości z dopasowanych wierzchołków lub krawędzi.

INTO \<ramka>

Zapisuje wynik zapytania w TableFrame o nazwie ramka.

Operacje na atrybutach dostępne w ramach słów kluczowych WHERE i RETURN obejmują:

  • operatory arytmetyczne +, -, x, /,
  • konkatenację tekstów, np. wezel.firstName + wezel.lastName as name,
  • wyszukiwanie wzorca w tekście: STARTS WITH, ENDS WITH, CONTAINS,
  • porównanie wartości: = (równość), <> (różne od), <, >, <=, >=, IS NULL, IS NOT NULL,
  • operatory boolowskie: AND, OR, NOT,
  • wybór z kolekcji: IN.

Funkcje agregujące, które można użyć w Trovares Query Language:

  • count(*) - zliczanie,
  • sum(*) - suma,
  • min() - znajdowanie minimum,
  • max() - znajdowanie maximum,
  • avg() - średnia.

Istnieją dwie funkcje specjalne do obliczania stopnia wierzchołka:

  • indegree(a) / indegree(a, ramkaKrawedzi) - oblicza liczbę krawędzi wchodzących do wierzchołka a (krawędzi z podanej ramki)
  • outdegree(a) / outdegree(a, ramkaKrawedzi) - oblicza liczbę krawędzi wychodzących z wierzchołka a (krawędzi z podanej ramki)

Wyszukiwanie klik

Kolejnym przykładem będzie znajdowanie klik rozmiaru trzy, tzn. takich grup trzech wierzchołków, że wszystkie one są połączone krawędziami.

Rysunek poniżej przedstawia przykładowy graf z zaznaczoną na czerwono kliką rozmiaru 3.

klika rozmiaru 3 Źródło grafiki: wiktionary

In [ ]:
%%time
server.drop_frame("results__Triangles")
query = """
MATCH (osoba1:ldbc__persons)-[zna1:ldbc__person_knows_person]->(osoba2:ldbc__persons)
    -[zna2:ldbc__person_knows_person]->(osoba3:ldbc__persons)
    -[zna3:ldbc__person_knows_person]->(osoba1:ldbc__persons)
WHERE 
    osoba1.id <> osoba2.id 
    AND osoba2.id <> osoba3.id
    AND osoba3.id <> osoba1.id
RETURN 
    osoba1.firstName + " " + osoba1.lastName as osoba1,
    osoba2.firstName + " " + osoba2.lastName as osoba2,
    osoba3.firstName + " " + osoba3.lastName as osoba3
INTO
    results__Triangles
"""

server.run_job(query)

Sprawdźmy ile różnych "trójkątów znaleziono"

In [ ]:
results = server.get_table_frame("results__Triangles")
results.num_rows

Zobaczmy pierwsze 10 trójek osób, które zwrócono w zapytaniu.

In [ ]:
results.get_data(length=10)

Kolejny przykład na wyszukiwanie wzorca

Wczytajmy komentarze (plik comment_0_0.csv) oraz relacje person likes comment (plik person_likes_comment_0_0.csv) i comment has creator (plik comment_hasCreator_person_0_0.csv).

In [ ]:
server.drop_frame("ldbc__comment_hasCreator_person")
server.drop_frame("ldbc__person_likes_comment")
server.drop_frame("ldbc__comments")
comments = server.create_vertex_frame(
        name='ldbc__comments',
        schema=[['creationDate', xgt.DATETIME], ['id', xgt.INT], ['locationIP', xgt.IPADDRESS], ['browserUsed', xgt.TEXT],
            ['content', xgt.TEXT], ['length', xgt.INT]],
        key='id')
comments.load("/home/kdmszkXX/workshop/social_network/comment_0_0.csv", headerMode=xgt.HeaderMode.IGNORE)

person_likes_comment = server.create_edge_frame(
        name='ldbc__person_likes_comment',
        schema=[['creationDate', xgt.DATETIME], ['Person.id', xgt.INT], ['Comment.id', xgt.INT]],
        source=persons,
        target=comments,
        source_key="Person.id",
        target_key="Comment.id")
person_likes_comment.load("/home/kdmszkXX/workshop/social_network/person_likes_comment_0_0.csv", headerMode=xgt.HeaderMode.IGNORE)

comment_hasCreator_person = server.create_edge_frame(
        name='ldbc__comment_hasCreator_person',
        schema=[['creationDate', xgt.DATETIME], ['Comment.id', xgt.INT], ['Person.id', xgt.INT]],
        source=comments,
        target=persons,
        source_key="Comment.id",
        target_key="Person.id")
comment_hasCreator_person.load("/home/kdmszkXX/workshop/social_network/comment_hasCreator_person_0_0.csv", headerMode=xgt.HeaderMode.IGNORE)
In [ ]:
print("Liczba komentarzy: " + str(comments.num_rows))
print("Liczba like'ow: " + str(person_likes_comment.num_rows))

Wybierzmy te komentarze, które dostały like'a od osoby, która zna ich autora.

In [ ]:
%%time
server.drop_frame("results__Comments")
query = """
MATCH (comment:ldbc__comments)<-[lubi:ldbc__person_likes_comment]-(osoba1:ldbc__persons)-[zna:ldbc__person_knows_person]->(osoba2:ldbc__persons),
    (osoba2:ldbc__persons)<-[created:ldbc__comment_hasCreator_person]-(comment:ldbc__comments)
RETURN 
    comment
INTO
    results__Comments
"""

server.run_job(query)

Sprawdźmy ile było takich komentarzy.

In [ ]:
results = server.get_table_frame("results__Comments")
results.num_rows

Ponadto sprawdźmy pierwsze 10 znalezionych wyników.

In [ ]:
results.get_data(length=10)

Rozkład stopni wierzchołków

Stopień wierzchołka to liczba krawędzi, które mają swój początek lub koniec w danym wierzchołku.

Policzmy rozkład stopni wierzchołków dla Person.

In [ ]:
%%time
server.drop_frame("results__Indegrees")
query = """
MATCH (a:ldbc__persons)
RETURN 
    indegree(a) + indegree(a)
INTO
    results__Indegrees
"""

server.run_job(query)

Sprawdźmy ile wyników otrzymaliśmy (liczba ta powinna być równa liczbie wierzchołków Person).

In [ ]:
results = server.get_table_frame("results__Indegrees")
results.num_rows

Sprawdźmy także jak wygląda pierwsze 10 wyników.

In [ ]:
results.get_data(length=10)

Zapisywanie danych

Do zapisywania danych służy funkcja VertexFrame.save(sciezka)/ EdgeFrame.save(sciezka) / TableFrame.save(sciezka), która zapisuje ramkę wierzchołków, ramkę krawędzi bądź rezultat zapytania do pliku .csv o podanej ścieżce.

In [ ]:
results.save("/home/kdmszkXX/workshop/social_network/result.csv")

Zadania do samodzielnej pracy

  1. Wybierz wszystkie osoby, które polubiły swój własny komentarz.
  2. Ile średnio komentarzy opublikowała jedna osoba?
In [ ]:
# miejsce na odpowiedz

Ostatnia aktualizacja: May 18, 2021
Ta strona używa plików cookies.
Polityka Prywatności    AKCEPTUJĘ