ArangoDB - Query di esempio AQL

In questo capitolo, prenderemo in considerazione alcune query di esempio AQL su un file Actors and MoviesBanca dati. Queste query si basano su grafici.

Problema

Data una raccolta di attori e una raccolta di film e una raccolta di bordi actIn (con una proprietà year) per collegare il vertice come indicato di seguito:

[Actor] <- act in -> [Movie]

Come otteniamo -

  • Tutti gli attori che hanno recitato in "movie1" O "movie2"?
  • Tutti gli attori che hanno recitato sia in "movie1" E "movie2"?
  • Tutti i film comuni tra "attore1" e "attore2"?
  • Tutti gli attori che hanno recitato in 3 o più film?
  • Tutti i film in cui hanno recitato esattamente 6 attori?
  • Il numero di attori per film?
  • Il numero di film per attore?
  • Il numero di film recitati tra il 2005 e il 2010 dall'attore?

Soluzione

Durante il processo di risoluzione e ottenimento delle risposte alle domande di cui sopra, useremo Arangosh per creare il set di dati ed eseguire query su questo. Tutte le query AQL sono stringhe e possono essere semplicemente copiate sul tuo driver preferito invece che su Arangosh.

Cominciamo creando un set di dati di prova in Arangosh. Innanzitutto, scarica questo file -

# wget -O dataset.js
https://drive.google.com/file/d/0B4WLtBDZu_QWMWZYZ3pYMEdqajA/view?usp=sharing

Produzione

...
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘dataset.js’
dataset.js [ <=> ] 115.14K --.-KB/s in 0.01s
2017-09-17 14:19:12 (11.1 MB/s) - ‘dataset.js’ saved [117907]

Puoi vedere nell'output sopra che abbiamo scaricato un file JavaScript dataset.js.Questo file contiene i comandi Arangosh per creare il set di dati nel database. Invece di copiare e incollare i comandi uno per uno, useremo il file--javascript.executeopzione su Arangosh per eseguire i comandi multipli in modo non interattivo. Consideralo il comando salvavita!

Ora esegui il seguente comando sulla shell:

$ arangosh --javascript.execute dataset.js

Fornisci la password quando richiesto, come puoi vedere nello screenshot qui sopra. Ora che abbiamo salvato i dati, costruiremo le query AQL per rispondere alle domande specifiche sollevate all'inizio di questo capitolo.

Prima domanda

Prendiamo la prima domanda: All actors who acted in "movie1" OR "movie2". Supponiamo di voler trovare i nomi di tutti gli attori che hanno recitato in "TheMatrix" O "TheDevilsAdvocate" -

Inizieremo con un film alla volta per ottenere i nomi degli attori -

127.0.0.1:[email protected]_system> db._query("FOR x IN ANY 'movies/TheMatrix' actsIn
OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN x._id").toArray();

Produzione

Riceveremo il seguente output:

[
   "actors/Hugo",
   "actors/Emil",
   "actors/Carrie",
   "actors/Keanu",
   "actors/Laurence"
]

Ora continuiamo a formare un UNION_DISTINCT di due query NEIGHBORS che saranno la soluzione -

127.0.0.1:[email protected]_system> db._query("FOR x IN UNION_DISTINCT ((FOR y IN ANY
'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN
y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true,
uniqueVertices: 'global'} RETURN y._id)) RETURN x").toArray();

Produzione

[
   "actors/Charlize",
   "actors/Al",
   "actors/Laurence",
   "actors/Keanu",
   "actors/Carrie",
   "actors/Emil",
   "actors/Hugo"
]

Seconda domanda

Consideriamo ora la seconda domanda: All actors who acted in both "movie1" AND "movie2". Questo è quasi identico alla domanda precedente. Ma questa volta non ci interessa un'UNIONE ma un'INTERSEZIONE -

127.0.0.1:[email protected]_system> db._query("FOR x IN INTERSECTION ((FOR y IN ANY
'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN
y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true,
uniqueVertices: 'global'} RETURN y._id)) RETURN x").toArray();

Produzione

Riceveremo il seguente output:

[
   "actors/Keanu"
]

Terza domanda

Consideriamo ora la terza domanda: All common movies between "actor1" and "actor2". Questo è in realtà identico alla domanda sugli attori comuni in movie1 e movie2. Dobbiamo solo cambiare i vertici iniziali. Ad esempio, cerchiamo di trovare tutti i film in cui Hugo Weaving ("Hugo") e Keanu Reeves sono co-protagonisti -

127.0.0.1:[email protected]_system> db._query(
   "FOR x IN INTERSECTION (
      (
         FOR y IN ANY 'actors/Hugo' actsIn OPTIONS 
         {bfs: true, uniqueVertices: 'global'}
          RETURN y._id
      ),
      
      (
         FOR y IN ANY 'actors/Keanu' actsIn OPTIONS 
         {bfs: true, uniqueVertices:'global'} RETURN y._id
      )
   ) 
   RETURN x").toArray();

Produzione

Riceveremo il seguente output:

[
   "movies/TheMatrixReloaded",
   "movies/TheMatrixRevolutions",
   "movies/TheMatrix"
]

Quarta domanda

Consideriamo ora la quarta domanda. All actors who acted in 3 or more movies. Questa domanda è diversa; non possiamo fare uso della funzione vicini qui. Al contrario, utilizzeremo l'edge-index e l'istruzione COLLECT di AQL per il raggruppamento. L'idea di base è raggruppare tutti i bordi per i lorostartVertex(che in questo set di dati è sempre l'attore). Quindi rimuoviamo tutti gli attori con meno di 3 film dal risultato poiché qui abbiamo incluso il numero di film in cui un attore ha recitato -

127.0.0.1:[email protected]_system> db._query("FOR x IN actsIn COLLECT actor = x._from WITH
COUNT INTO counter FILTER counter >= 3 RETURN {actor: actor, movies:
counter}"). toArray()

Produzione

[
   {
      "actor" : "actors/Carrie",
      "movies" : 3
   },
   
   {
      "actor" : "actors/CubaG",
      "movies" : 4
   },

   {
      "actor" : "actors/Hugo",
      "movies" : 3
   },

   {
      "actor" : "actors/Keanu",
      "movies" : 4
   },

   {
      "actor" : "actors/Laurence",
      "movies" : 3
   },

   {
      "actor" : "actors/MegR",
      "movies" : 5
   },

   {
      "actor" : "actors/TomC",
      "movies" : 3
   },
   
   {
      "actor" : "actors/TomH",
      "movies" : 3
   }
]

Per le restanti domande, discuteremo la formazione delle query e forniremo solo le query. Il lettore dovrebbe eseguire la query da solo sul terminale Arangosh.

Quinta domanda

Consideriamo ora la quinta domanda: All movies where exactly 6 actors acted in. La stessa idea della query precedente, ma con il filtro di uguaglianza. Tuttavia, ora abbiamo bisogno del film invece dell'attore, quindi restituiamo il file_to attribute -

db._query("FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER
counter == 6 RETURN movie").toArray()

Il numero di attori per film?

Ricordiamo nel nostro set di dati _to sul bordo corrisponde al film, quindi contiamo quante volte lo stesso _toappare. Questo è il numero di attori. La query è quasi identica a quelle precedenti mawithout the FILTER after COLLECT -

db._query("FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter RETURN
{movie: movie, actors: counter}").toArray()

Sesta domanda

Consideriamo ora la sesta domanda: The number of movies by an actor.

Il modo in cui abbiamo trovato le soluzioni alle nostre query precedenti ti aiuterà a trovare la soluzione anche a questa query.

db._query("FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter
RETURN {actor: actor, movies: counter}").toArray()