Graph Data Models — Cypher, SPARQL, Datalog: Ba cách tiếp cận dữ liệu đồ thị (DDIA)

Mở đầu
Ảnh: Brett Sayles — Pexels
Ở phần trước, chúng ta đã thấy mô hình relational (quan hệ) và document (dạng tài liệu) — mỗi loại có thế mạnh riêng. Nhưng có một kiểu dữ liệu mà cả hai đều xử lý khá vất vả: dữ liệu đồ thị (graph data).
Khi dữ liệu của bạn có quá nhiều mối quan hệ chằng chịt kiểu nhiều-nhiều (many-to-many) — như mạng xã hội, hệ thống gợi ý sản phẩm, hay map địa lý — thì graph database mới là lựa chọn tối ưu. Và mỗi graph database lại có ngôn ngữ truy vấn riêng: Cypher, SPARQL, và Datalog. Ba cái tên này khác nhau ra sao?
Bài này sẽ phân tích từng loại, dựa trên một ví dụ xuyên suốt: biểu diễn quê quán của người dùng trong hệ thống — với các thực thể như USA, Idaho, Europe, và mối quan hệ "nằm trong" (within).
Property Graph Model — Mô hình đồ thị tính chất
Property Graph là mô hình phổ biến nhất trong graph database hiện nay (tiêu biểu là Neo4j). Nó có 2 thành phần chính:
- Vertex (đỉnh / nút) — Mỗi vertex có một định danh duy nhất, một tập các thuộc tính (properties) dạng key-value, và một tập các cạnh kết nối
- Edge (cạnh / quan hệ) — Mỗi edge có một định danh, một đỉnh bắt đầu (tail vertex) và đỉnh kết thúc (head vertex), một nhãn (label) mô tả kiểu quan hệ, và các thuộc tính riêng
Điểm mạnh của property graph là tính linh hoạt: bạn không cần schema cố định. Một vertex có thể có thuộc tính khác nhau tuỳ loại, và bạn có thể thêm edge mới bất cứ lúc nào mà không cần migration. Quan trọng hơn, mỗi edge đều có thể mang dữ liệu riêng — ví dụ quan hệ "đã kết hôn" có thể có thuộc tính "từ ngày" (since), "nơi tổ chức" (location).
Cypher — Ngôn ngữ truy vấn đồ thị "trực quan"
Cypher là ngôn ngữ truy vấn khai báo (declarative) của Neo4j. Điểm đặc biệt là cú pháp của nó rất trực quan — bạn "vẽ" pattern đồ thị ngay trong câu truy vấn bằng ký hiệu ASCII art.
Nhìn vào cú pháp là thấy ngay:
MATCH (person) -[:BORN_IN]-> () -[:WITHIN*0..]-> (location:Location {name: 'Europe'})
RETURN person.name
Trong đó (person) là vertex, -[:BORN_IN]-> là edge có label BORN_IN. () là một vertex ẩn danh trung gian, và [:WITHIN*0..] là phép duyệt đệ quy — đi theo quan hệ WITHIN không giới hạn số bước. Cú pháp này biểu diễn câu hỏi: "Người nào sinh ra ở một địa điểm thuộc châu Âu?"
Ảnh: Brett Sayles — Pexels
Cypher dùng cơ chế pattern matching — công cụ tối ưu hoá sẽ tìm tất cả cách khớp pattern trong đồ thị. Với phần [:WITHIN*0..], nó có thể duyệt từ Idaho → USA → North America → ... cho tới khi tìm được Europe. Nếu không có đường đi, kết quả trả về rỗng.
SPARQL — Chuẩn semantic web
SPARQL là ngôn ngữ truy vấn cho mô hình RDF (Resource Description Framework) — một tiêu chuẩn của W3C cho dữ liệu đồ thị trên web. Thay vì property graph, RDF dùng triple: subject → predicate → object.
Ví dụ triple: ID_1 :within ID_2 — mỗi câu đều có chủ ngữ, vị ngữ, tân ngữ. Không có khái niệm "thuộc tính gắn trên edge" như property graph; thay vào đó, mọi thứ đều là triple.
Câu truy vấn tương tự trong SPARQL:
SELECT ?personName WHERE {
?person :bornIn / :within* ?location .
?location rdfs:label "Europe" .
}
Cú pháp SPARQL dùng dấu chấm (.) để ngăn cách các triple pattern, và dấu gạch (/) thể hiện đường đi — tương tự xpath. SPARQL mạnh ở khả năng kết hợp dữ liệu từ nhiều nguồn RDF khác nhau trên web, nhờ cơ chế namespace (prefix) chuẩn hoá.
Tuy nhiên, SPARQL cũng phức tạp hơn Cypher ở chỗ nó yêu cầu phân biệt giữa đỉnh (URI), giá trị (literal) và biến. Và RDF triple store thường kém hiệu quả hơn property graph trong các tác vụ duyệt đồ thị thuần tuý.
Datalog — Logic programming cho dữ liệu đồ thị
Datalog là một nhánh của Prolog được thiết kế riêng cho truy vấn cơ sở dữ liệu. Thay vì pattern matching, Datalog tiếp cận vấn đề bằng suy luận logic (logical inference).
Dữ liệu được biểu diễn dưới dạng các sự kiện (facts):
name(usa, 'United States').
type(usa, country).
within(idaho, usa).
within(usa, north_america).
within(north_america, europe). # Ở đời thực sai, nhưng để làm ví dụ
Và truy vấn được viết dưới dạng các luật (rules):
within_recursive(Location, Location) :- name(Location, _).
within_recursive(Location, InRegion) :- within(Location, Middle),
within_recursive(Middle, InRegion).
Câu hỏi "Ai sinh ra ở châu Âu?" sẽ là:
?- person(Person), born_in(Person, Loc), within_recursive(Loc, 'Europe').
Ảnh: Vladimir Srajber — Pexels
Điểm mạnh của Datalog là tính suy luận — nó cho phép định nghĩa quan hệ mới từ các quan hệ cơ bản. Nếu bạn muốn tìm "tất cả địa điểm thuộc châu Âu theo cấp bậc", bạn chỉ cần viết một rule đệ quy duy nhất. Điểm yếu là cú pháp khó đọc hơn và đòi hỏi tư duy logic học thuật.
So sánh ba ngôn ngữ
| Tiêu chí | Cypher | SPARQL | Datalog |
|---|---|---|---|
| Mô hình dữ liệu | Property Graph | RDF Triple | Facts + Rules |
| Cú pháp | ASCII art, dễ đọc | Triple pattern, phức tạp | Logic, học thuật |
| Đệ quy | Hỗ trợ ([:WITHIN*]) | Hỗ trợ (/ :within*) | Hỗ trợ (rule đệ quy) |
| Tính biểu diễn | Cao, gần gũi dev | Rất cao, chuẩn W3C | Cao nhất, suy luận logic |
| Sử dụng chính | Neo4j, graph app | Semantic web, dữ liệu mở | Học thuật, phân tích |
Một điểm thú vị: Datalog có sức mạnh biểu diễn ngang hàng với đại số quan hệ (relational algebra), nên nó có thể mô phỏng cả SQL và các ngôn ngữ đồ thị. Tuy nhiên, ít người dùng Datalog trong thực tế vì nó yêu cầu tư duy "khai báo luật" thay vì "mô tả kết quả muốn có".
Key Takeaways
- Graph data model — Lựa chọn tối ưu cho dữ liệu có nhiều quan hệ nhiều-nhiều và truy vấn duyệt đồ thị
- Property Graph vs RDF — Property Graph (Neo4j) linh hoạt hơn với dữ liệu thực tế; RDF phù hợp cho tích hợp dữ liệu liên web
- Cypher — Dễ học, trực quan, pattern matching mạnh mẽ với cú pháp ASCII art
- SPARQL — Chuẩn hoá, kết nối nhiều nguồn, nhưng cú pháp phức tạp và triple store kém hiệu quả hơn
- Datalog — Mạnh nhất về mặt lý thuyết, cho phép suy luận và truy vấn đệ quy phức tạp
- Chọn ngôn ngữ tuỳ bài toán — Không có ngôn ngữ "tốt nhất", chỉ có ngôn ngữ phù hợp nhất với nhu cầu
📋 Phụ lục thuật ngữ
| Vertex | Đỉnh/nút trong đồ thị, tương đương row trong SQL |
| Edge | Cạnh/quan hệ giữa hai vertex, có thể mang thuộc tính riêng |
| Property Graph | Mô hình đồ thị mà cả vertex và edge đều có thuộc tính key-value |
| RDF Triple | Bộ ba Subject-Predicate-Object, mô hình dữ liệu của Semantic Web |
| Cypher | Ngôn ngữ truy vấn đồ thị khai báo của Neo4j, dùng pattern matching |
| SPARQL | Ngôn ngữ truy vấn RDF chuẩn W3C |
| Datalog | Ngôn ngữ truy vấn dạng logic programming, kế thừa từ Prolog |
Kết
Graph data model không phải lúc nào cũng cần thiết — nếu dữ liệu của bạn có cấu trúc cây đơn giản hoặc quan hệ 1-nhiều, relational hoặc document đã đủ dùng. Nhưng khi bạn gặp những bài toán mà mối quan hệ là trung tâm của dữ liệu (social graph, recommendation engine, network topology), thì graph database là cứu cánh.
Và khi đã chọn graph, việc hiểu rõ Cypher, SPARQL, Datalog sẽ giúp bạn chọn đúng công cụ. Đa số dev sẽ chọn Cypher vì tính trực quan. SPARQL dành cho ai làm việc với dữ liệu mở liên kết. Datalog dành cho người thích suy luận và muốn sức mạnh biểu diễn tối đa.
Bài tiếp theo trong series DDIA sẽ nói về Storage and Retrieval — cách dữ liệu được lưu và đọc từ đĩa. Một chủ đề cốt lõi khác không kém.