Thiết lập Edge Collection và quan hệ giữa các Vertex
Bước đầu tiên để xây dựng mô hình Graph là xác định các thực thể (Vertex) và mối quan hệ (Edge). Trong ArangoDB, quan hệ được lưu trữ trong Edge Collection, nơi mỗi Edge chứa tham chiếu đến Vertex nguồn và đích.
Tạo Edge Collection với tên "follows" để mô tả mối quan hệ "người này theo dõi người kia". Tham số fromVertexCollections và toVertexCollections buộc ArangoDB chỉ cho phép Edge nối giữa các Vertex thuộc các Collection đã định nghĩa, đảm bảo tính toàn vẹn dữ liệu.
arangosh --javascript "db._createCollection('follows', { edges: true, fromVertexCollections: ['users'], toVertexCollections: ['users'] });"
Kết quả mong đợi: Console hiển thị thông báo "Collection 'follows' created" và cấu trúc collection hiện ra với thuộc tính "type: edge".
Chèn dữ liệu Vertex và Edge cùng lúc
Sử dụng AQL để chèn một tập hợp dữ liệu mẫu bao gồm Vertex và Edge trong cùng một lệnh, giúp giảm độ trễ mạng và đảm bảo tính nguyên tử của giao dịch.
Lệnh sau sẽ tạo 3 người dùng (Vertex) và thiết lập các mối quan hệ theo dõi (Edge) giữa họ. Cú pháp [ { _from: 'users/1001', _to: 'users/1002' } ] dùng để định nghĩa Edge.
arangosh --javascript "
db._query('
WITH users, follows
FOR v IN [
{ _key: \"alice\", name: \"Alice\", role: \"admin\" },
{ _key: \"bob\", name: \"Bob\", role: \"user\" },
{ _key: \"charlie\", name: \"Charlie\", role: \"user\" }
]
INSERT v INTO users
RETURN \"Users created\"
').toArray();
db._query('
WITH users, follows
FOR e IN [
{ _from: \"users/alice\", _to: \"users/bob\", type: \"follows\" },
{ _from: \"users/bob\", _to: \"users/charlie\", type: \"follows\" },
{ _from: \"users/charlie\", _to: \"users/alice\", type: \"follows\" }
]
INSERT e INTO follows
RETURN \"Edges created\"
').toArray();
"
Kết quả mong đợi: Trả về mảng chứa hai chuỗi xác nhận "Users created" và "Edges created". Dữ liệu đã được lưu vào cả Collection Vertex và Edge.
Verify kết quả thiết lập Graph
Để kiểm tra xem quan hệ đã được thiết lập chính xác chưa, hãy truy vấn tất cả Edge trong collection "follows" và hiển thị đầy đủ các thuộc tính _from và _to.
arangosh --javascript "db._query('FOR e IN follows RETURN e').toArray();"
Kết quả mong đợi: Một mảng JSON chứa 3 object Edge, mỗi object có thuộc tính _from và _to trỏ đúng đến các _id của Vertex đã tạo (ví dụ: "users/alice").
Thực hiện truy vấn đồ thị phức tạp với AQL
AQL (ArangoDB Query Language) cung cấp các toán tử mạnh mẽ để duyệt đồ thị mà không cần viết logic phức tạp ở phía ứng dụng.
Truy vấn tìm đường đi (Path) giữa hai Vertex
Sử dụng toán tử LET ... = ANY( ... IN OUTBOUND ...) để tìm một đường đi cụ thể giữa hai điểm. Điều này hữu ích khi cần kiểm tra xem hai người dùng có liên kết trực tiếp hay gián tiếp với nhau.
Lệnh dưới đây tìm đường đi từ "alice" đến "charlie" thông qua các Edge trong collection "follows".
arangosh --javascript "
db._query('
LET startNode = DOCUMENT(\"users/alice\")
LET endNode = DOCUMENT(\"users/charlie\")
LET path = ANY(
p IN 1..3 OUTBOUND startNode follows
FILTER p.vertices[-1]._id == endNode._id
RETURN p
)
RETURN path
').toArray();
"
Kết quả mong đợi: Trả về một object Path chứa mảng vertices (bao gồm alice, bob, charlie) và mảng edges (các quan hệ nối giữa chúng).
Áp dụng thuật toán PageRank để phân tích ảnh hưởng
ArangoDB có tích hợp sẵn hàm GRAPH_ANALYSIS hoặc COLLECTION_ANALYSIS để tính toán các chỉ số đồ thị như PageRank. PageRank giúp xác định Vertex nào có "độ nổi tiếng" hoặc "ảnh hưởng" cao nhất trong mạng lưới.
Thực hiện tính toán PageRank trên toàn bộ Graph đã tạo. Tham số maxIterations xác định độ chính xác, dampingFactor là hệ số suy giảm (thường là 0.85).
arangosh --javascript "
db._query('
RETURN GRAPH_ANALYSIS(
{
vertexCollections: [\"users\"],
edgeCollections: [\"follows\"],
type: \"pagerank\",
options: {
maxIterations: 10,
dampingFactor: 0.85
}
}
)
').toArray();
"
Kết quả mong đợi: Trả về một object chứa danh sách các Vertex kèm theo điểm số score. Vertex được nhiều người theo dõi nhất sẽ có điểm số cao nhất.
Tối ưu hóa chỉ mục (Index) cho truy vấn đồ thị
Trong các truy vấn đồ thị, việc lọc Vertex dựa trên thuộc tính (như _key hoặc _id) xảy ra rất thường xuyên. Nếu không có chỉ mục, ArangoDB phải quét toàn bộ collection (Full Scan), gây chậm đáng kể trên dữ liệu lớn.
Tạo chỉ mục nhất (Unique Index) cho _key
Mặc định ArangoDB tự tạo chỉ mục cho _id, nhưng nếu bạn thường xuyên truy vấn bằng _key (ví dụ: "users/alice"), việc tạo chỉ mục Unique cho _key là bắt buộc để đảm bảo tốc độ và tính duy nhất.
Tạo chỉ mục Unique cho trường "_key" trong collection "users".
arangosh --javascript "db.users.ensureIndex({ type: 'unique', fields: ['_key'] });"
Kết quả mong đợi: Trả về object mô tả chỉ mục mới với type: unique và fields: ["_key"].
Tạo chỉ mục Geo hay Fulltext (nếu cần)
Nếu dữ liệu Vertex chứa thông tin địa lý (longitude, latitude) hoặc văn bản cần tìm kiếm, hãy tạo chỉ mục tương ứng để tối ưu truy vấn AQL phức tạp.
Tạo chỉ mục Geo cho trường "location" (giả định bạn đã có trường này) để hỗ trợ truy vấn tìm người dùng gần đó trong Graph.
arangosh --javascript "db.users.ensureIndex({ type: 'geo', fields: ['location'] });"
Kết quả mong đợi: Chỉ mục Geo được tạo thành công, sẵn sàng cho các truy vấn geoDistance hoặc geoWithin.
Verify hiệu năng với EXPLAIN
Sử dụng từ khóa EXPLAIN trước lệnh truy vấn để xem kế hoạch thực thi (Execution Plan). Kiểm tra xem ArangoDB có đang dùng chỉ mục (Index Scan) hay đang quét toàn bộ (Collection Scan).
Thực hiện EXPLAIN cho truy vấn tìm Vertex theo _key.
arangosh --javascript "
db._query('
EXPLAIN FOR v IN users FILTER v._key == \"alice\" RETURN v
').toArray();
"
Kết quả mong đợi: Trong object trả về, trường nodes phải chứa một bước có type: "IndexNode" và indexName trỏ đến chỉ mục bạn vừa tạo. Nếu thấy type: "CollectionNode" hoặc type: "AllNodes", nghĩa là chỉ mục chưa hoạt động đúng.
Điều hướng series:
Mục lục: Series: Triển khai Database Multi-Model với ArangoDB trên Ubuntu 24.04
« Phần 2: Khám phá giao diện web (ArangoShell) và quản lý Database
Phần 4: Kết hợp dữ liệu Document và Key-Value trong cùng một Collection »