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

Można połączyć ze sobą źródła danych i utworzyć spersonalizowane rekomendacje dla użytkownika. Jednak duża ilość danych potrzebnych do przetworzenia rekomendacji opartych na grafach na dużą skalę znacznie ogranicza możliwość wykonania filtrowania kolaboratywnego w aplikacji produkcyjnej. 

W tym rozdziale i notatniku podzielimy złożony problem grafowy filtrowania kolaboratywnego na części, które można przeszukiwać w czasie rzeczywistym. W ten sposób porzucimy przetwarzanie komponentów wymagających masowego przetwarzania.

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

**&#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): Schemat grafu do obliczeń krawędzi skrótowych
#### [Krok 2](#step2): Wczytywanie danych
#### [Krok 3](#step3): Obliczanie krawędzi skrótowych
#### [Krok 4](#step4): Schemat grafu i wczytywanie danych dla rekomendacji w środowisku produkcyjnym
#### [Krok 5](#step5): Przeszukiwanie krawędzi skrótowych dla rekomendacji

--------------------CELL_MARKDOWN_3--------------------
## <div id="step1"></div>Krok 1: Schemat grafu do obliczeń krawędzi skrótowych
[Początek &#x2191;](#topKey)
[Następne: Wczytywanie danych &#x2193;](#step2)
--------------------CELL_MARKDOWN_4--------------------
Model danych dla rozdziału 12. służący do obliczeń krawędzi skrótowych 
![ch12_sc_edge_model](https://raw.githubusercontent.com/datastax/graph-book/master/notebooks/images/schema/ch12_schema_shortcut.png "Schemat do obliczeń krawędzi skrótowych w przykładzie rekomendacji filmów.")
--------------------CELL_MARKDOWN_5--------------------
#### Etykiety wierzchołków
--------------------CELL_GREMLIN_6--------------------
schema.vertexLabel('Movie').
       ifNotExists().
       partitionBy('movie_id', Bigint).
       property("tmdb_id", Text).
       property("imdb_id", Text).
       property("movie_title", Text).
       property("release_date", Text).
       property("production_company", Text).
       property("overview", Text).
       property("popularity", Double).
       property("budget", Bigint).
       property("revenue", Bigint).
       create();

schema.vertexLabel('User').
       ifNotExists().
       partitionBy('user_id', Int).
       property('user_name', Text). // Augmented, Random Data
       create();
--------------------CELL_MARKDOWN_7--------------------
#### Etykiety krawędzi
--------------------CELL_GREMLIN_8--------------------
schema.edgeLabel('rated').
      ifNotExists().
      from('User').
      to('Movie').
      clusterBy('rating', Double).
      property('timestamp', Text).
      create()
--------------------CELL_MARKDOWN_9--------------------
#### Indeksy krawędzi
--------------------CELL_GREMLIN_10--------------------
schema.edgeLabel('rated').
       from('User').
       to('Movie').
       materializedView('User__rated__Movie_by_Movie_movie_id_rating').
       ifNotExists().
       inverse().
       clusterBy('rating', Asc).
       create()

--------------------CELL_MARKDOWN_11--------------------
## <div id="step2"></div>Krok 2: Wczytywanie danych do obliczeń krawędzi skrótowych
[Początek &#8593;](#topKey)
[Wstecz: Schemat &#x21b5;](#step1)
[Następne: Obliczanie krawędzi skrótowych &#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 12. <tt>./ch12_load_shortcut_example.sh</tt>
2. Uaktualnij ścieżki, aby wskazywały na poprawne katalogi w lokalnym środowisku
3. Uruchom skrypt: <tt>./ch12_load_shortcut_example.sh</tt>
--------------------CELL_MARKDOWN_13--------------------
## <div id="step3"></div>Krok 3: Obliczanie krawędzi skrótowych
[Początek &#8593;](#topKey)
[Wstecz: Wczytywanie danych &#x21b5;](#step2)
[Następne: Schemat grafu i wczytywanie danych dla rekomendacji w środowisku produkcyjnym &#x2193;](#step4)
--------------------CELL_MARKDOWN_14--------------------
### Krawędzie skrótowe z wykorzystaniem punktacji NPS
--------------------CELL_GREMLIN_15--------------------
movie_ids = g.V().has("User","user_id", 694).out("rated").
                  values("movie_id")
--------------------CELL_MARKDOWN_16--------------------
#### Sprawdźmy jak obliczyliśmy rekomendacje dla jednego filmu: 588
--------------------CELL_GREMLIN_17--------------------
g.V().has("Movie","movie_id",588).valueMap()
--------------------CELL_MARKDOWN_18--------------------
#### 1000 pierwszych rekomendacji dla filmu Aladdin

Te wyniki zostały obliczone na podstawie próbki 100k ocen; wyniki przedstawione w tekście uzyskasz licząc rekomendacje ze wszystkich 20M rekomendacji z serwisu MovieLens Ratings, dostępnych pod adresem: https://grouplens.org/datasets/movielens/
--------------------CELL_GREMLIN_19--------------------
movie_id = 588
g.withSack(0.0).             
   V().has("Movie","movie_id", movie_id).  
     aggregate("originalMovie").           
   inE("rated").has("rating", P.gte(4.5)).outV().
  outE("rated").                               
      choose(values('rating').is(P.gte(4.0)),
             sack(sum).by(constant(1.0)),  
             sack(minus).by(constant(1.0))).     
      inV().                                     
  where(without('originalMovie')).            
  group().                                     
     by().               
     by(sack().sum()).                        
  unfold().                                     
  order().                                      
     by(values, desc).              
  limit(1000).                                  
    project("original", "recommendation", "score").
            by(select("originalMovie")).         
            by(select(keys)).             
            by(select(values)).           
    toList()
--------------------CELL_MARKDOWN_20--------------------
## <div id="step4"></div>Krok 4: Schemat grafu i wczytywanie danych dla rekomendacji w środowisku produkcyjnym
[Początek &#8593;](#topKey)
[Wstecz: Obliczanie krawędzi skrótowych &#x21b5;](#step3)
[Następne: Przeszukiwanie krawędzi skrótowych dla rekomendacji &#x2193;](#step5)

--------------------CELL_MARKDOWN_21--------------------
### Użyliśmy wszystkich 20M ocen z serwisu MovieLens do obliczenia krawędzi skrótowych. Usuńmy te dane i model, aby wczytać krawędzie i sprawdzić jak utworzyć rekomendacje na ich podstawie.
--------------------CELL_GREMLIN_22--------------------
schema.drop()
--------------------CELL_MARKDOWN_23--------------------
Model danych z rozdziału 12. do obliczeń krawędzi skrótowych 
![ch12_sc_edge_model](https://raw.githubusercontent.com/datastax/graph-book/master/notebooks/images/schema/ch12_schema_prod.png "Finalny schemat produkcyjny wykorzystujący krawędzie skrótowe w przykładzie rekomendacji filmów.")
--------------------CELL_MARKDOWN_24--------------------
#### Etykiety wierzchołków i krawędzi:
--------------------CELL_GREMLIN_25--------------------
schema.vertexLabel('Movie').
       ifNotExists().
       partitionBy('movie_id', Bigint).
       property("tmdb_id", Text).
       property("imdb_id", Text).
       property("movie_title", Text).
       property("release_date", Text).
       property("production_company", Text).
       property("overview", Text).
       property("popularity", Double).
       property("budget", Bigint).
       property("revenue", Bigint).
       create();

schema.vertexLabel('User').
       ifNotExists().
       partitionBy('user_id', Int).
       property('user_name', Text). // Uzupełnione dane losowe
       create();
--------------------CELL_GREMLIN_26--------------------
schema.edgeLabel('rated').
      ifNotExists().
      from('User').
      to('Movie').
      clusterBy('timestamp', Text, Desc).  // Uwaga: zmiana klucza klastra
      property('rating', Text).
      create()

schema.edgeLabel('recommend').
      ifNotExists().
      from('Movie').
      to('Movie').
      clusterBy('nps_score', Double, Desc).
      create()
--------------------CELL_MARKDOWN_27--------------------
## Ponowne wczytanie danych, w celu użycia krawędzi skrótowych

#### 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 12. <tt>./ch12_load_production.sh</tt>
2. Uaktualnij ścieżki, aby wskazywały na poprawne katalogi w lokalnym środowisku
3. Uruchom skrypt: <tt>./ch12_load_production.sh</tt>
--------------------CELL_MARKDOWN_28--------------------
## <div id="step5"></div>Krok 5: Przeszukiwanie krawędzi skrótowych dla rekomendacji
[Początek &#8593;](#topKey)
[Wstecz: Schemat grafu i wczytywanie danych dla rekomendacji w środowisku produkcyjnym &#x21b5;](#step4)
--------------------CELL_MARKDOWN_29--------------------
#### Zapytanie: What are the top 5 recommendations for Aladdin?
--------------------CELL_GREMLIN_30--------------------
g.V().has("Movie", "movie_id", 588).as("original_movie").
     outE("recommend").
     limit(5).
     project("Original","Recommendation", "Score").
       by(select("original_movie").values("movie_title")).
       by(inV().values("movie_title")).
       by(values("nps_score"))
--------------------CELL_MARKDOWN_31--------------------
#### Zapytanie 1: Trzy pierwsze rekomendacje na podstawie najnowszej oceny wystawionej przez użytkownika
--------------------CELL_GREMLIN_32--------------------
g.V().has("User","user_id", 694).      // użytkownik
      outE("rated").limit(1).inV().    // pierwsza krawędź "rated" jest najnowszą
      outE("recommend").limit(3).      // trzy pierwsze elementy dotyczą 3 najlepszych rekomendacji
      project("Recommendation", "Score").  // tworzenie mapy z dwoma kluczami
        by(inV().values("movie_title")).   // przechodzimy do filmów; pobieramy tytuł
        by(values("nps_score"))            // pozostajemy na krawędziach; pobieramy punktację
    
--------------------CELL_MARKDOWN_33--------------------
#### Zapytanie 2: Najlepsza rekomendacja dla trzech najnowszych ocen wystawionych przez użytkownika
--------------------CELL_GREMLIN_34--------------------
g.V().has("User","user_id", 694).   // użytkownik
      outE("rated").limit(3).inV(). // trzy ostatnio ocenione filmy 
      project("rated_movie", "recommended_movie", "nps_score"). // mapa z trzema kluczami
        by("movie_title").          // wartość dla klucza "rated_movie"
        by(outE("recommend").       // wartość dla klucza "recommended_movie"
           limit(1).                // pierwsza rekomendacja ma najwyższą wartość
           inV().values("movie_title")). // przejście do filmu i pobranie tytułu
        by(outE("recommend").       // wartość dla klucza "nps_score"
           limit(1).                // pierwsza rekomendacja ma najwyższą wartość
           values("nps_score"))     // zostajemy na krawędzi; pobieramy punktację
--------------------CELL_MARKDOWN_35--------------------
#### Zapytanie 3: Trzy najlepsze rekomendacje dla każdej z trzech najnowszych ocen wystawionych przez użytkownika
--------------------CELL_GREMLIN_36--------------------
g.V().has("User","user_id", 694).       // użytkownik
     outE("rated").limit(3).inV().      // 3 ostatnio ocenione filmy
     local(outE("recommend").limit(3)). // 3 najlepsze rekomendacje dla każdego filmu
     group().                           // tworzenie mapy
       by(inV().values("movie_title")). // klucze dla mapy; scalanie duplikatów
       by(values("nps_score").sum()).   // wartości; sumowanie wartości dla duplikatów
     order(local).                      // sortowanie mapy
       by(values, desc)                 // według jej wartości w kolejności malejącej
--------------------CELL_MARKDOWN_37--------------------
### Koniec notatnika
[Top &#8593;](#topKey)

