Các thao tác cơ bản với Dgraph Database

Tram Ho

Lý do có series này

Đơn giản là muốn nhờ Viblo note lại những kiến thức học được trong một ngày thôi. Đây không phải là các bài blog chia sẻ hoàn chỉnh nên mọi người có thể không cần để ý đến nó

Lý do học Dgraph

Hôm nay mưa to quá và COVID thì chưa có dấu hiệu dừng lại. Dự là sẽ còn phải remote tránh dịch dài dài nên ngoài các công việc hàng ngày mình vẫn phải làm ra thì thời gian được dôi thêm khá nhiều (1 – 2h một ngày ý). Thế là lọ mọ lên Github như một thói quen check Github discovery thấy có cái này đang trending trong topic của GraphQL nên quyết định dành ra vài giờ để học nó biết đâu sau này có việc dùng.

Bắt đầu học

Bắt đầu với Dgraph

  • Cài đặt Dgraph với Docker

  • Khái niệm về nodes: Trong Graph Database tất cả các thực thể hoặc các khái niệm đều được biểu diễn dưới dạng các nodes. Nó có thể là các giao dịch, các mặt hàng, các person … tất cả các thực thể đó đều được biểu diễn dưới dạng node.
  • Khái niệm về cạnh edges: Tất cả các quan hệ giữa các nốt được biểu diễn bằng các cạnh. Ví dụ trong hình sau:


Thì chúng ta có hai node biểu diễn 2 người và một cạnh biểu diễn quan hệ follows giữa chúng. Có thể thấy hai node này có hai thuộc tính là agename. Tất cả các thuộc tính trong một node được gọi chung là predicates trong Dgraph. Cạnh follows giữa hai node này cũng được gọi là một predicate mặc dù nó không phải là một string hay một số nguyên mà nó trỏ đến một node khác.

Tạo mới một node

Tất cả các thao tác như create , update ,delete trong Dgraph đều được gọi là mutations. Chúng ta hay thử thêm một đoạn dữ liệu mới bằng cách vào trong tab mutate

Thêm vào đoạn dữ liệu sau:

Đoạn dữ liệu này sẽ khởi tạo hai node biểu thị cho 2 person. Tuy nhiên nó chưa thể hiện mối quan hệ giữa hai node. Để thể hiện mối quan hệ đó chúng ta cần có ột chút thay đổi nhỏ:

Query với hàm has

Thử sư rdungj mode query

Sẽ list tất cả các danh sách các node có predicate name và trong data trả về sẽ có trương people giống như RESTful

Tạo schema động

Ngay khi thêm các predicate vào trong graph thì Dgraph mặc định sẽ sinh ra các schema tương ứng. Điều này khiến cho ứng dụng của chúng ta khá uyển chuyển tuy nhiên nếu như chúng ta muốn ràng buộc các trường nhập vào cũng phải theo một schema cố định thì cũng sẽ có cách (sẽ tìm hiểu trong những bài tiếp theo)

Các thao tác xử lý dữ liệu cơ bản

Thao tác với UID

Khi mọt node được tạo ra trên graph sẽ tồn tại tơng ứng một uid và việc thêm các predicate hay update, xoá có thể thực hiện với các uid này. Việc này giống với việc sử dụng khoá chính trong cơ sở dữ liệu quan hệ. Chúng ta thử ví dụ sau:

Ví dụ này sẽ tạo ra hai user và cho chúng follow lẫn nhau. Khi cần update chúng ta cũng cần phải truyền tương ứng các uid vào. Để query chúng ta sẽ sử dụng

và thu được kết quả như sau:

Thêm cạnh bằng uid

Chúng ta muốn thêm một user nưa vào dánh sách follow của user có uid = 0x2 như sau:

Duyệt qua các cạnh.

Như vậy chúng ta đã thấy có quan hệ User 1 follow User 2 và User 2 follow User 3. Chúng ta có thể duyệt qua các cạnh này bằng cách follow như sau:

Ta được kết quả như sau

Nhưng cách này thực sự không được gọn cho lắm. Chúng ta có thể sử dungj đệ quy để gọi

Ta cũng thu được kết quả tương tự

Xoá một predicate trong node

Để xoá một thuộc tính trong một node chúng ta sử dụng cú pháp sau

Tương tự để xoá đi một follow chúng ta cũng có thể sử dụng cú pháp

Các kiểu dữ liệu cơ bản trong DGraph

Để minh hoa cho phần này chúng ta sẽ xây dựng một ứng dụng blog nhỏ có mô hình như sau:

Đồ thị trên bao gồm 3 thực thể là Author, Blog Post và các Tags. Có một vài ràng buộc trong graph này như sau

  • Tất cả các Author trong graph có thể có 1 hoặc nhiều blog post. Cạnh published biểu diễn mối quan hệ giữa một bài post và author của nó. Cạnh này có gốc ở Author và đỉnh ở Blog node
  • Tất cả các blog post có thể có 1 hoặc nhiều tags. Cạnh tagged biểu diễn mối quan hệ giữa blog post và các tags của chúng. Cạnh này bắt đầu từ blog post node và trỏ đến tag node.

Bây giờ thì dựng graph thôi

Sau khi dựng graph sang phần query để truy vấn thử

Sau đó thu được graph như sau:

Trong graph trên chúng ta thấy có

  • 3 node author màu xanh dương
  • mỗi author có 2 blog post màu xah lá cây
  • mỗi post có một vài tag màu hồng, có thể là các tag riêng hoặc nhiều post share chung một vài common tag

Kiểu dữ liệu cho các predicates

Bình thường thì các kiểu dữ liệu cho các predicate sẽ được tự động detect sau khi tạo graph thành công. Có thể xem trên hình

Các kiểu dữ liệu cơ bản bao gồm string, float, int hay uid và Dgraph còn có nhiều kểu dữ liệu khác như geo, datetime, boolean trong đó

  • Kiểu uid cung cấp cạnh liên kết giữa hai node
  • Mảng [uid] biểu diễn một collections của các uid biểu thị cho việc biểu diễn nhiều relationships

Truy vấn giá trị của các predicates

Ngoài việc sử dụng hàm has như trên thì chúng ta còn có các hàm khác sử dụng để truy vấn dữ liệu với các ý nghĩa lần lượt như hình dưới

Chúng ta cùng thử ví dụ tìm ra các best_author với rule là các điểm rating cao hơn 4.0

Tuy nhiên chúng ta thấy kết quả báo trường rating chưa được đánh index

Note: Chúng táex không thể query giá trị của một predicate nếu như predicate đó chưa được đánh index

Đánh index cho predicate

Indexx là kĩ thuật giúp cho việc query trên predicate được thực hiện với tốc độ nhanh hơn và nó là bắt buộc khi muốn query giá trị của một predicate. Dgraph cung cấp các loại index khác nhau cho từng kiểu dữ liệu cụ thể như trong bảng sau

Để đặt index có thể sử dụng tab Schema trên giao diện

Sau khi đánh index chúng ta tiến hành query lại và sẽ nhận được kết quả thành công

Filter cạnh trên query

Câu query trên giúp chúng ta lấy các thông tin của author. Giờ chúng ta muốn lấy thêm các blog post tương ứng của author đó thì làm thế nào

Chúng a thu được kết quả như sau

Bây giờ muốn filter các bài viết với số lượng dislike nhỏ hơn 12 thì làm thế nào. Chúng ta sử dụng @filter nó giống như một decorator của Python. Lúc này câu query sẽ trở thành

Và chúng ta cũng cần phải đánh index cho predicate dislikes này. Sau đó thu được kết quả như sau:

Query với string predicate

Với predicate kiểu dữ liệu là string thì trước tiên cũng cần phải đánh index cho chúng. Tuy nhiên index của predicate string này có nhiều loại khác nhau

trong đó ý nghĩa từng loại như sau:

  • fulltext, term, trigram là một vài loại cao siêu hơn (giống như tokenizer trong NLP)
  • exact index chỉ sử dụng cho các query eq, gt, lt, ge, le ngoài ra sử dụng các query khác sẽ báo lỗi
  • hash index sẽ giúp cho việc query eq được nhanh hơn nhưng chỉ dùng cho eq thôi

Sau đó query thử

Query với reverse edges

Trong đồ thị chúng ta nhìn thấy lúc đầu thì các relationship đang là 1 chiều. Vậy nên nếu muốn querry các bài viết đã gắn thẻ xuất phát từ node tags thì câu truy vấn sau không có tác dụng

Muốn làm như vậy thì cần phải thêm mode reverse vào tagged bằng cách thêm ~tagged. Query thử thấy xuất hiện lỗi do chưa đánh reverse

Sau khi đánh rerverse xong thì kết quả thu được

Tổng kết và nhận xét

  • Dùng Dgraph khá dễ dàng
  • Thao tác trên RavelUI rất tiện và trực quan
  • Các thao tác với dữ liệu khá đơn giản
  • Kì vọng một cái gì đó hay ho hơn nhưng cảm nhận chung là nó khá dễ dùng và trực quan
Chia sẻ bài viết ngay

Nguồn bài viết : Viblo