ArangoDB - Truy vấn mẫu AQL

Trong chương này, chúng ta sẽ xem xét một số Truy vấn Ví dụ AQL về Actors and MoviesCơ sở dữ liệu. Các truy vấn này dựa trên đồ thị.

Vấn đề

Đưa ra một bộ sưu tập các diễn viên và một bộ sưu tập phim và một bộ sưu tập các cạnh actIn (với thuộc tính năm) để kết nối đỉnh như được chỉ ra bên dưới -

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

Làm thế nào để chúng tôi nhận được -

  • Tất cả các diễn viên đã tham gia diễn xuất trong "movie1" HOẶC "movie2"?
  • Tất cả các diễn viên đã tham gia cả "movie1" VÀ "movie2"?
  • Tất cả các bộ phim chung giữa "Actor1" và "Actor2"?
  • Tất cả các diễn viên đã đóng từ 3 phim trở lên?
  • Tất cả các phim có chính xác 6 diễn viên tham gia?
  • Số lượng diễn viên của phim?
  • Số lượng phim của diễn viên?
  • Số lượng các bộ phim đã tham gia diễn xuất từ ​​năm 2005 đến năm 2010 của diễn viên?

Giải pháp

Trong quá trình giải quyết và thu được câu trả lời cho các câu hỏi trên, chúng tôi sẽ sử dụng Arangosh để tạo tập dữ liệu và chạy các truy vấn trên đó. Tất cả các truy vấn AQL đều là chuỗi và có thể đơn giản sao chép sang trình điều khiển yêu thích của bạn thay vì Arangosh.

Chúng ta hãy bắt đầu bằng cách tạo Tập dữ liệu thử nghiệm trong Arangosh. Trước tiên, hãy tải xuống tệp này -

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

Đầu ra

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

Bạn có thể thấy trong đầu ra ở trên rằng chúng tôi đã tải xuống một tệp JavaScript dataset.js.Tệp này chứa các lệnh Arangosh để tạo tập dữ liệu trong cơ sở dữ liệu. Thay vì sao chép và dán từng lệnh một, chúng tôi sẽ sử dụng--javascript.executetrên Arangosh để thực hiện nhiều lệnh không tương tác. Hãy coi đó là lệnh cứu mạng!

Bây giờ thực hiện lệnh sau trên shell:

$ arangosh --javascript.execute dataset.js

Cung cấp mật khẩu khi được nhắc như bạn có thể thấy trong ảnh chụp màn hình ở trên. Bây giờ chúng ta đã lưu dữ liệu, vì vậy chúng ta sẽ xây dựng các truy vấn AQL để trả lời các câu hỏi cụ thể được nêu ra ở đầu chương này.

Câu hỏi đầu tiên

Hãy để chúng tôi trả lời câu hỏi đầu tiên: All actors who acted in "movie1" OR "movie2". Giả sử, chúng tôi muốn tìm tên của tất cả các diễn viên đã đóng trong "TheMatrix" HOẶC "TheDevilsAdvocate" -

Chúng ta sẽ bắt đầu với từng bộ phim một để biết tên của các diễn viên -

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

Đầu ra

Chúng tôi sẽ nhận được kết quả sau:

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

Bây giờ chúng tôi tiếp tục tạo một UNION_DISTINCT gồm hai truy vấn NEIGHBORS sẽ là giải pháp -

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

Đầu ra

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

Câu hỏi thứ hai

Bây giờ chúng ta hãy xem xét câu hỏi thứ hai: All actors who acted in both "movie1" AND "movie2". Điều này gần giống với câu hỏi trên. Nhưng lần này chúng tôi không quan tâm đến CÔNG ĐOÀN mà quan tâm đến sự TRUYỀN CẢM HỨNG -

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

Đầu ra

Chúng tôi sẽ nhận được kết quả sau:

[
   "actors/Keanu"
]

Câu hỏi thứ ba

Bây giờ chúng ta hãy xem xét câu hỏi thứ ba: All common movies between "actor1" and "actor2". Điều này thực sự giống với câu hỏi về các diễn viên thường gặp trong movie1 và movie2. Chúng ta chỉ cần thay đổi các đỉnh bắt đầu. Ví dụ: chúng ta hãy tìm tất cả các bộ phim mà Hugo Weaving ("Hugo") và Keanu Reeves cùng đóng -

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

Đầu ra

Chúng tôi sẽ nhận được kết quả sau:

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

Câu hỏi thứ tư

Bây giờ chúng ta hãy xem xét câu hỏi thứ tư. All actors who acted in 3 or more movies. Câu hỏi này là khác nhau; chúng ta không thể sử dụng chức năng hàng xóm ở đây. Thay vào đó, chúng ta sẽ sử dụng chỉ mục cạnh và câu lệnh COLLECT của AQL để phân nhóm. Ý tưởng cơ bản là nhóm tất cả các cạnh theostartVertex(trong tập dữ liệu này luôn là tác nhân). Sau đó, chúng tôi xóa tất cả các diễn viên có ít hơn 3 phim khỏi kết quả vì ở đây chúng tôi đã bao gồm số phim mà một diễn viên đã tham gia -

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

Đầu ra

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

Đối với các câu hỏi còn lại, chúng tôi sẽ thảo luận về việc hình thành truy vấn và chỉ cung cấp các truy vấn. Người đọc nên tự chạy truy vấn trên thiết bị đầu cuối Arangosh.

Câu hỏi thứ năm

Bây giờ chúng ta hãy xem xét câu hỏi thứ năm: All movies where exactly 6 actors acted in. Ý tưởng tương tự như trong truy vấn trước đó, nhưng với bộ lọc bình đẳng. Tuy nhiên, bây giờ chúng tôi cần bộ phim thay vì diễn viên, vì vậy chúng tôi trả lại_to attribute -

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

Số lượng diễn viên của phim?

Chúng tôi nhớ trong tập dữ liệu của mình _to ở rìa tương ứng với bộ phim, vì vậy chúng tôi tính tần suất _toxuất hiện. Đây là số lượng diễn viên. Truy vấn gần giống với những truy vấn trước đó nhưngwithout the FILTER after COLLECT -

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

Câu hỏi thứ sáu

Bây giờ chúng ta hãy xem xét câu hỏi thứ sáu: The number of movies by an actor.

Cách chúng tôi tìm ra giải pháp cho các truy vấn ở trên cũng sẽ giúp bạn tìm ra giải pháp cho truy vấn này.

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