ArangoDB - Exemples de requêtes AQL

Dans ce chapitre, nous examinerons quelques exemples de requêtes AQL sur un Actors and MoviesBase de données. Ces requêtes sont basées sur des graphiques.

Problème

Étant donné une collection d'acteurs et une collection de films, et une collection de bords actIn (avec une propriété year) pour connecter le sommet comme indiqué ci-dessous -

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

Comment pouvons-nous -

  • Tous les acteurs qui ont joué dans "movie1" OU "movie2"?
  • Tous les acteurs qui ont joué à la fois dans "movie1" ET "movie2"?
  • Tous les films communs entre «acteur1» et «acteur2»?
  • Tous les acteurs qui ont joué dans 3 films ou plus?
  • Tous les films où exactement 6 acteurs ont joué?
  • Le nombre d'acteurs par film?
  • Le nombre de films par acteur?
  • Le nombre de films joués entre 2005 et 2010 par acteur?

Solution

Au cours du processus de résolution et d'obtention des réponses aux requêtes ci-dessus, nous utiliserons Arangosh pour créer l'ensemble de données et exécuter des requêtes à ce sujet. Toutes les requêtes AQL sont des chaînes et peuvent simplement être copiées sur votre pilote préféré au lieu d'Arangosh.

Commençons par créer un jeu de données de test dans Arangosh. Tout d'abord, téléchargez ce fichier -

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

Production

...
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]

Vous pouvez voir dans la sortie ci-dessus que nous avons téléchargé un fichier JavaScript dataset.js.Ce fichier contient les commandes Arangosh pour créer l'ensemble de données dans la base de données. Au lieu de copier et coller les commandes une par une, nous utiliserons le--javascript.executeoption sur Arangosh pour exécuter les multiples commandes de manière non interactive. Considérez cela comme la commande de sauvetage!

Maintenant, exécutez la commande suivante sur le shell -

$ arangosh --javascript.execute dataset.js

Fournissez le mot de passe lorsque vous y êtes invité, comme vous pouvez le voir dans la capture d'écran ci-dessus. Maintenant que nous avons sauvegardé les données, nous allons donc construire les requêtes AQL pour répondre aux questions spécifiques soulevées au début de ce chapitre.

Première question

Prenons la première question: All actors who acted in "movie1" OR "movie2". Supposons que nous voulions trouver les noms de tous les acteurs qui ont joué dans "TheMatrix" OU "TheDevilsAdvocate" -

Nous commencerons par un film à la fois pour obtenir les noms des acteurs -

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();

Production

Nous recevrons la sortie suivante -

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

Maintenant, nous continuons à former un UNION_DISTINCT de deux requêtes NEIGHBORS qui sera la solution -

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();

Production

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

Deuxième question

Examinons maintenant la deuxième question: All actors who acted in both "movie1" AND "movie2". C'est presque identique à la question ci-dessus. Mais cette fois nous ne sommes pas intéressés par une UNION mais par une INTERSECTION -

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();

Production

Nous recevrons la sortie suivante -

[
   "actors/Keanu"
]

Troisième question

Examinons maintenant la troisième question: All common movies between "actor1" and "actor2". C'est en fait identique à la question sur les acteurs communs dans movie1 et movie2. Nous devons juste changer les sommets de départ. A titre d'exemple, trouvons tous les films où Hugo Weaving ("Hugo") et Keanu Reeves co-vedette -

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();

Production

Nous recevrons la sortie suivante -

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

Quatrième question

Examinons maintenant la quatrième question. All actors who acted in 3 or more movies. Cette question est différente; nous ne pouvons pas utiliser la fonction voisins ici. À la place, nous utiliserons l'index de bord et l'instruction COLLECT d'AQL pour le regroupement. L'idée de base est de regrouper toutes les arêtes par leurstartVertex(qui dans cet ensemble de données est toujours l'acteur). Ensuite, nous supprimons tous les acteurs avec moins de 3 films du résultat, car nous avons inclus ici le nombre de films dans lesquels un acteur a joué -

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()

Production

[
   {
      "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
   }
]

Pour les questions restantes, nous discuterons de la formation des requêtes et fournirons uniquement les requêtes. Le lecteur doit exécuter la requête lui-même sur le terminal Arangosh.

Cinquième question

Considérons maintenant la cinquième question: All movies where exactly 6 actors acted in. La même idée que dans la requête précédente, mais avec le filtre d'égalité. Cependant, maintenant nous avons besoin du film au lieu de l'acteur, donc nous retournons le_to attribute -

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

Le nombre d'acteurs par film?

Nous nous souvenons dans notre ensemble de données _to sur le bord correspond au film, donc nous comptons à quelle fréquence le même _toapparaît. C'est le nombre d'acteurs. La requête est presque identique à celles précédentes maiswithout the FILTER after COLLECT -

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

Sixième question

Examinons maintenant la sixième question: The number of movies by an actor.

La façon dont nous avons trouvé des solutions à nos requêtes ci-dessus vous aidera également à trouver la solution à cette requête.

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