--------------------NOTEBOOK_Ch7_Trees_Production--------------------
--------------------CELL_MARKDOWN_1--------------------
# ![bono](https://raw.githubusercontent.com/datastax/graph-book/master/notebooks/images/logos/grem-7.png) Rozdział 7 
## Używanie drzew w środowisku produkcyjnym
Autor notatnika: [Denise Gosnell](https://twitter.com/DeniseKGosnell)

Niezależnie od tego czy modelujesz struktury korporacyjne czy nieograniczone sieci czujników IoT, dane hierarchiczne świetnie nadają się do analizy za pomocą grafów. Jednak prostota, związana z analizą złożonych problemów drzewiastych przesłania złożoność przetwarzania naturalnych danych hierarchicznych. Ten rozdział i notatnik prezentują (prawie) wszystkie techniki potrzebne do rozpoczęcia korzystania z drzew w swoich danych.

---------------

**&#9888;** Nie wszystkie komórki rozwijają się domyślnie. Ich treść jest ukryta, jak w przypadku tej komórki. Kliknij oko w prawym rogu komórki, aby wyświetlić i ukryć kod komórki.
--------------------CELL_MARKDOWN_2--------------------
## <div id="topKey"></div>Ten notatnik jest podzielony na pięć części:
#### [Krok 1](#step1): Tworzenie schematu grafu
#### [Krok 2](#step2): Wstawianie danych
#### [Krok 3](#step3): Zapytania Gremlina: od liści do korzeni (lub: z dołu na górę)
#### [Krok 4](#step4): Zapytania Gremlina: od korzeni do liści (lub: z góry na dół)
#### [Krok 5](#step5): Wykorzystanie zapytań w scenariuszach awarii wieży
--------------------CELL_MARKDOWN_3--------------------
## <div id="step1"></div>Krok 1: Tworzenie schematu grafu
[Początek &#x2191;](#topKey)
[Następne: Wstawianie danych &#x2193;](#step2)
--------------------CELL_MARKDOWN_4--------------------
Produkcyjny model danych dla rozdziału 7.:
![ch7_model](https://raw.githubusercontent.com/datastax/graph-book/master/notebooks/images/schema/ch7_schema.png "Schemat produkcyjny dla przykładu sieci czujników.")
--------------------CELL_MARKDOWN_5--------------------
#### Tworzenie etykiet wierzchołków
--------------------CELL_GREMLIN_6--------------------
schema.vertexLabel('Sensor').
       ifNotExists().
       partitionBy('sensor_name', Text).
       property('latitude', Double).
       property('longitude', Double).
       property('coordinates', Point).
       create();

schema.vertexLabel('Tower').
       ifNotExists().
       partitionBy('tower_name', Text).
       property('latitude', Double).
       property('longitude', Double).
       property('coordinates', Point).
       create();
--------------------CELL_MARKDOWN_7--------------------
#### Tworzenie etykiet krawędzi
--------------------CELL_GREMLIN_8--------------------
schema.edgeLabel('send').
       ifNotExists().
       from('Sensor').
       to('Sensor').
       clusterBy('timestep', Int, Desc).
       create()

schema.edgeLabel('send').
       ifNotExists().
       from('Sensor').
       to('Tower').
       clusterBy('timestep', Int, Desc).
       create()
--------------------CELL_MARKDOWN_9--------------------
#### Tworzenie perspektyw zmaterializowanych
--------------------CELL_GREMLIN_10--------------------
schema.edgeLabel('send').
       from('Sensor').
       to('Sensor').
       materializedView('sensor_sensor_inv').
       ifNotExists().
       inverse().
       create()

schema.edgeLabel('send').
       from('Sensor').
       to('Tower').
       materializedView('sensor_tower_inv').
       ifNotExists().
       inverse().
       create()
--------------------CELL_MARKDOWN_11--------------------
## <div id="step2"></div>Krok 2: Wstawianie danych
[Początek &#8593;](#topKey)
[Wstecz: Schemat &#x21b5;](#step1)
[Następne: Zapytania Gremlina: od liści do korzeni (lub: z dołu na górę) &#x2193;](#step3)
--------------------CELL_MARKDOWN_12--------------------
#### Wykonaj poniższe instrukcje dotyczące importowania danych grafowych za pomocą narzędzia DataStax Bulk Loader.

Oto instrukcje:
1. Otwórz skrypt do wczytywania danych dla rozdziału 7. <tt>./ch7_load.sh</tt>
2. Uaktualnij ścieżki, aby wskazywały na poprawne katalogi w lokalnym środowisku
3. Uruchom skrypt: <tt>./ch7_load.sh</tt>
--------------------CELL_MARKDOWN_13--------------------
## <div id="step3"></div>Krok 3: Zapytania Gremlina: od liści do korzeni 
[Początek &#8593;](#topKey)
[Wstecz: Wstawianie danych &#x21b5;](#step2)
[Następne: Zapytania Gremlina: od korzeni do liści (lub: z góry na dół) &#x2193;](#step4)
--------------------CELL_MARKDOWN_14--------------------
#### Zapytanie: Dokąd i kiedy czujnik wysłał dane?
--------------------CELL_GREMLIN_15--------------------
sensor = g.V().has("Sensor", "sensor_name", "104115939").next() 
g.V(sensor).                             // szukamy czujnika
    outE("send").                        // wychodzimy na zewnątrz i zatrzymujemy się na każdej krawędzi
    project("Label", "Name", "Time").    // tworzymy mapę dla każdej krawędzi
      by(__.inV().                       // przejście do wierzchołka
            label()).                    // wartości dla pierwszego klucza
      by(__.inV().                       // przejście do wierzchołka
           coalesce(values("tower_name"),// wartości dla drugiego klucza jeśli jest to wieża 
                    values("sensor_name"))). // w przeciwnym razie zwracamy wartość sensor_name 
      by(values("timestep"))             // wartości dla trzeciego klucza: "Time"
--------------------CELL_MARKDOWN_16--------------------
#### Znajdź **wszystkie** drzewa prowadzące od czujnika do wieży z uwzględnieniem czasu.
--------------------CELL_GREMLIN_17--------------------
sensor = g.V().has("Sensor", "sensor_name", "104115939").next()
g.V(sensor).                     // szukamy czujnika
    as("start").                 // oznaczamy go etykietą początkowego czujnika
  until(hasLabel("Tower")).      // dopóki nie dotrzemy do wieży
  repeat(outE("send").           // przechodzimy dalej przez krawędzie send
           as("send_edge").      // oznaczamy je etykietą "send_edge"
         inV().                  // przechodzimy do sąsiedniego wierzchołk
           as("visited").  // oznaczamy go etykietą "visited"
          simplePath()).         // usuwamy cykle
  as("tower"). // wszystkie wierzchołki są wieżami, oznaczamy je etykietą "tower"
  path().      // pobieramy drogę wierzchołków i krawędzi od wierzchołka "start" do "tower"
    by(coalesce(values("tower_name"), // 1. obiekt na drodze jest wierzchołkiem
                values("sensor_name"))).
    by(values('timestep'))            // 2. obiekt na drodze jest krawędzią
--------------------CELL_MARKDOWN_18--------------------
#### Znajdź **poprawne** drzewa wychodzące z określonego czujnika.
--------------------CELL_GREMLIN_19--------------------
sensor = g.V().has("Sensor", "sensor_name", "104115939").next()
g.V(sensor).                               // szukamy czujnika
    outE("send").has("timestep", 0).inV(). // przejście przez krawędzie z wartością timestep = 0
    outE("send").has("timestep", 1).inV(). // przejście przez krawędzie z wartością timestep = 1
    outE("send").has("timestep", 2).inV(). // przejście przez krawędzie z wartością timestep = 2
    outE("send").has("timestep", 3).inV(). // przejście przez krawędzie z wartością timestep = 3
    outE("send").has("timestep", 4).inV(). // przejście przez krawędzie z wartością timestep = 4
    outE("send").has("timestep", 5).inV(). // przejście przez krawędzie z wartością timestep = 5
    path().                                // pobieramy drogę od czujnika
      by(coalesce(values("tower_name"),    // dla elementów parzystych 
                  values("sensor_name"))). // pobieramy identyfikator wierzchołka
      by(values('timestep'))               // dla elementów nieparzystych
--------------------CELL_MARKDOWN_20--------------------
#### Znajdź **poprawne** drzewa wychodzące z określonego czujnika zgodnie z czasem.
--------------------CELL_GREMLIN_21--------------------
sensor = g.V().has("Sensor", "sensor_name", "104115939").next()
g.V(sensor).as("start").          // szukamy czujnika i oznaczamy go etykietą
   until(hasLabel("Tower")).      // dopóki nie dotrzemy do wieży
   repeat(outE("send").           // przechodzimy dalej krawędziami send
            as("send_edge").      // oznaczamy je etykietą "send_edge"
          where(eq("send_edge")). // filtr: test równości
            by(loops()).          // krawędź przechodzi przez filtr jeśli wartość loops() jest równa
            by("timestep").       // wartości właściwości timestep na krawędzi
          inV().                  // przechodzimy do sąsiedniego wierzchołka
            as("visited")).       // oznaczamy go etykietą "visited"
   as("tower").                   // gwarancja wieży; oznaczamy ją etykietą "tower"
   path().                        // droga od wierzchołka "start" do wierzchołka "tower"
    by(coalesce(values("tower_name"),   // dla elementów parzystych 
                values("sensor_name"))).// pobieramy ID wierzchołka na podstawie jego etykiety  
    by(values('timestep'))              // dla elementów nieparzystych: czas

--------------------CELL_MARKDOWN_22--------------------
## <div id="step4"></div>Krok 4: Zapytania Gremlina: od korzeni do liści
[Początek &#8593;](#topKey)
[Wstecz: Zapytania Gremlina: od liści do korzeni &#x21b5;](#step3)
[Następne: Wykorzystanie zapytań w scenariuszach awarii wieży &#x2193;](#step5)
--------------------CELL_MARKDOWN_23--------------------
#### Zapytanie: Które czujniki są bezpośrednio połączone z wieżą Georgetown według czasu?
--------------------CELL_GREMLIN_24--------------------
tower = dev.V().has("Tower", "tower_name", "Georgetown").next()
g.V(tower).
    inE("send").
    project("Label", "Name", "Time").// tworzenie mapy dla każdej krawędzi
      by(outV().label()).            // wartość dla pierwszego klucza "Label"
      by(outV().                     // wartość dla drugiego klucza "Name"
         coalesce(values("tower_name"),    // jeśli jest to wieża, zwracamy tower_name
                  values("sensor_name"))). // w przeciwnym razie zwracamy sensor_name
      by(values("timestep"))         // wartość trzeciego klucza "Time"
--------------------CELL_MARKDOWN_25--------------------
#### Zapytanie: Jakie prawidłowe drogi wiodą od wieży Georgetown w dół do wszystkich czujników?
--------------------CELL_GREMLIN_26--------------------
start = 3
tower = dev.V().has("Tower", "tower_name", "Georgetown").next()
g.withSack(start).  // każdy obiekt przejścia zaczyna przejście z obiektem sack o wartości 3
  V(tower).as("start").              // pobieramy wieżę Georgetown
  repeat(inE("send").as("send_edge").// przechodzimy do krawędzi przychodzących 
         where(eq("send_edge")).     // tworzymy filtr równości:
           by(sack()).               // sprawdzamy, czy wartość obiektu sack()
           by("timestep").           // jest równa wartości timestep na krawędzi
         sack(minus).                // zmniejszamy wartość obiektu sack
           by(constant(1)).          // o 1
         outV().as("visited")).      // przechodzimy do sąsiedniego wierzchołka
   times(start+1).                   // czterokrotnie wykonujemy wiersze od 5. do 10.
   as("tower").         // ten wierzchołek przeszedł przez wszystkie filtry
   path().              // pobieramy drogę do niego począwszy od wierzchołka Georgetown
     by(coalesce(values("tower_name"),// pierwszy obiekt na drodze jest wierzchołkiem
                 values("sensor_name"))).
     by(values('timestep'))          // drugi obiekt na drodze jest krawędzią
--------------------CELL_MARKDOWN_27--------------------
#### Zapytanie: Jakie prawidłowe drogi wiodą od wieży Georgetown w dół do wszystkich czujników? (usuwanie cykli)
--------------------CELL_GREMLIN_28--------------------
start = 3
tower = dev.V().has("Tower", "tower_name", "Georgetown").next()
g.withSack(start).  
  V(tower).as("start").              
  repeat(inE("send").as("send_edge").
         where(eq("send_edge")).    
           by(sack()).              
           by("timestep").          
         sack(minus).                
           by(constant(1)).          
         outV().as("visited").
         simplePath()).        // usuwanie cykli
   times(start+1).                   
   as("tower").         
   path().              
     by(coalesce(values("tower_name"),
                 values("sensor_name"))).
     by(values('timestep')) 
--------------------CELL_MARKDOWN_29--------------------
## <div id="step5"></div>Krok 5: Wykorzystanie zapytań w scenariuszach awarii wieży
[Początek &#8593;](#topKey)
[Wstecz: Zapytania Gremlina: od korzeni do liści &#x21b5;](#step4)
--------------------CELL_MARKDOWN_30--------------------
#### Implementacja 1.: Pobieranie listy czujników połączonych z wieżą Georgetown w dowolnym oknie czasowym
--------------------CELL_GREMLIN_31--------------------
// umieszczenie zapytania o prawidłowe drogi w metodzie o nazwie getSensorsFromTower
def getSensorsFromTower(g, start, tower){
    sensors = g.withSack(start).V(tower).as("startingTower").
                        repeat(inE("send").as("sendEdge").
                               where(eq("sendEdge")).
                                   by(sack()).
                                   by("timestep").
                               sack(minus).
                               by(constant(1)).
                               outV().as("visitedVertex").
                               simplePath()).
                        times(start+1).
                        as("endingSensor").
                        select("endingSensor").
                        by(values("sensor_name")).
                        toList()
    return sensors;
}
// pobranie wierzchołka wieży Georgetown             
tower = g.V().has("Tower", "tower_name", "Georgetown").next();

// tworzenie listy czujników
atRiskSensors = [];  

// pętla przez okno czasowe
for(time = 0; time < 6; time++){  
    // tworzenie listy wszystkich czujników komunikujących się w tym czasie z wieżą Georgetown za pomocą metody getSensorsFromTower()
    atRiskSensors.add(getSensorsFromTower(g, time, tower));
}

// spłaszczenie listy do unikalnych identyfikatorów czujników
atRiskSensors = atRiskSensors.flatten().unique();
--------------------CELL_MARKDOWN_32--------------------
#### Implementacja 2.: Znajdź wszystkie wieże, z którymi komunikowały się zagrożone czujniki
--------------------CELL_GREMLIN_33--------------------
// umieszczenie zapytania o prawidłowe drogi w metodzie getTowersFromSensor
def getTowersFromSensor(g, start, sensor) {
    towers = g.withSack(start).V(sensor).as("startingSensor").
                until(hasLabel("Tower")).
                repeat(outE("send").as("sendEdge").
                       where(eq("sendEdge")).
                         by(sack()).
                         by("timestep").
                       inV().
                       as("visitedVertex").
                       sack(sum).
                       by(constant(1))).
                as("endingTower").
                select("endingTower").
                by(values("tower_name")).
                dedup().
                toList()
    return towers;
}

otherTowers = [:];                         // tworzenie mapy

for(i=0; i < atRiskSensors.size(); i++){  // pętla przez wszystkie czujniki
    otherTowers[atRiskSensors[i]] = [];    // inicjalizacja mapy dla czujników
    sensor = g.V().has("Sensor", "sensor_name", atRiskSensors[i]).next();
    for(time = 0; time < 6; time++){      // pętla przez okno czasowe
        // użycie metody getTowersFromSensor w celu dodania wszystkich wież do mapy dla tego czujnika w tym czasie
        otherTowers[atRiskSensors[i]].add(getTowersFromSensor(g, time, sensor));
    }
    // spłaszczenie listy do unikalnych identyfikatorów czujników
    otherTowers[atRiskSensors[i]] = otherTowers[atRiskSensors[i]].flatten().
                                                                  unique();
}
otherTowers
--------------------CELL_MARKDOWN_34--------------------
#### Koniec notatnika
