ArangoDB - Consultas de ejemplo de AQL

En este capítulo, consideraremos algunas consultas de ejemplo de AQL en un Actors and MoviesBase de datos. Estas consultas se basan en gráficos.

Problema

Dada una colección de actores y una colección de películas, y una colección actIn edge (con una propiedad de año) para conectar el vértice como se indica a continuación:

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

¿Cómo llegamos?

  • ¿Todos los actores que actuaron en "película1" O "película2"?
  • ¿Todos los actores que actuaron tanto en "película1" como en "película2"?
  • ¿Todas las películas comunes entre "actor1" y "actor2"?
  • ¿Todos los actores que actuaron en 3 o más películas?
  • ¿Todas las películas donde actuaron exactamente 6 actores?
  • ¿El número de actores por película?
  • ¿La cantidad de películas por actor?
  • ¿El número de películas interpretadas entre 2005 y 2010 por actor?

Solución

Durante el proceso de resolución y obtención de respuestas a las consultas anteriores, usaremos Arangosh para crear el conjunto de datos y ejecutar consultas sobre eso. Todas las consultas AQL son cadenas y simplemente se pueden copiar a su controlador favorito en lugar de Arangosh.

Comencemos por crear un conjunto de datos de prueba en Arangosh. Primero, descargue este archivo -

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

Salida

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

Puede ver en el resultado anterior que hemos descargado un archivo JavaScript dataset.js.Este archivo contiene los comandos de Arangosh para crear el conjunto de datos en la base de datos. En lugar de copiar y pegar los comandos uno por uno, usaremos el--javascript.executeopción en Arangosh para ejecutar los múltiples comandos de forma no interactiva. ¡Considérelo el comando de salvavidas!

Ahora ejecute el siguiente comando en el shell:

$ arangosh --javascript.execute dataset.js

Proporcione la contraseña cuando se le solicite, como puede ver en la captura de pantalla anterior. Ahora que hemos guardado los datos, construiremos las consultas AQL para responder las preguntas específicas planteadas al comienzo de este capítulo.

Primera pregunta

Tomemos la primera pregunta: All actors who acted in "movie1" OR "movie2". Supongamos que queremos encontrar los nombres de todos los actores que actuaron en "TheMatrix" O "TheDevilsAdvocate" -

Comenzaremos con una película a la vez para obtener los nombres de los actores:

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

Salida

Recibiremos el siguiente resultado:

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

Ahora continuamos formando un UNION_DISTINCT de dos consultas NEIGHBORS que serán la solución -

127.0.0.1:8529@_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();

Salida

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

Segunda pregunta

Consideremos ahora la segunda pregunta: All actors who acted in both "movie1" AND "movie2". Esto es casi idéntico a la pregunta anterior. Pero esta vez no nos interesa una UNIÓN sino una INTERSECCIÓN -

127.0.0.1:8529@_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();

Salida

Recibiremos el siguiente resultado:

[
   "actors/Keanu"
]

Tercera pregunta

Consideremos ahora la tercera pregunta: All common movies between "actor1" and "actor2". En realidad, esto es idéntico a la pregunta sobre actores comunes en movie1 y movie2. Solo tenemos que cambiar los vértices iniciales. Como ejemplo, busquemos todas las películas en las que Hugo Weaving ("Hugo") y Keanu Reeves son coprotagonistas.

127.0.0.1:8529@_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();

Salida

Recibiremos el siguiente resultado:

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

Cuarta pregunta

Consideremos ahora la cuarta pregunta. All actors who acted in 3 or more movies. Esta pregunta es diferente; no podemos hacer uso de la función de vecinos aquí. En su lugar, haremos uso del índice de borde y la declaración COLLECT de AQL para agrupar. La idea básica es agrupar todos los bordes por sustartVertex(que en este conjunto de datos es siempre el actor). Luego, eliminamos a todos los actores con menos de 3 películas del resultado, ya que aquí hemos incluido la cantidad de películas en las que ha actuado un actor:

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

Salida

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

Para las preguntas restantes, discutiremos la formación de la consulta y solo proporcionaremos las consultas. El lector debe ejecutar la consulta por sí mismo en la terminal de Arangosh.

Quinta pregunta

Consideremos ahora la quinta pregunta: All movies where exactly 6 actors acted in. La misma idea que en la consulta anterior, pero con el filtro de igualdad. Sin embargo, ahora necesitamos la película en lugar del actor, así que devolvemos el_to attribute -

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

¿El número de actores por película?

Recordamos en nuestro conjunto de datos _to en el borde corresponde a la película, por lo que contamos con qué frecuencia el mismo _toaparece. Este es el número de actores. La consulta es casi idéntica a las anteriores, perowithout the FILTER after COLLECT -

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

Sexta pregunta

Consideremos ahora la sexta pregunta: The number of movies by an actor.

La forma en que encontramos soluciones a nuestras consultas anteriores también lo ayudará a encontrar la solución a esta consulta.

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