Và theo logic thì chỉ bấy nhiêu thơi là đủ. Khơng có bảng, khơng giống như thơng thường nhưng lại đầy đủ và hơn cả những gì chúng ta mong muốn. Đáp ứng các mối liên hệ giữa các thực thể một cách chặt chẽ nhất. Và việc di chuyển hay thêm hoặc bớt thực thể hay bất cứ thứ gì trong mơ hình để phù hợp với nhu cầu kinh doanh đều khơng thành vấn đề.
2.2.1.3Các mơ hình đa miền
Trong thực tế có thể thấy rằng gần như khơng có vấn đề gì tồn tại độc lập mà thường phải kết hợp với nhau. Ta có thể xét ví dụ sau:
Hình 2.9 Ví dụ mơ hình đa miền
Trong hình này, ta có thể thấy 3 lĩnh vực cùng được thể hiện.
Đầu tiên là lĩnh vực văn học với các nút như Shakespeare với firstname là William và lastname là Shakespeare. Nút này được nối với vở kịch Julius Caesar và The Tempest. Có thể thấy tiếp trong sơ đồ có thơng tin về cơng ty Royal Shakespeare (RSC) là nút có khóa là company và giá trị là RSC. Lĩnh vực này kết nối với lĩnh vực trước bằng quan hệ PRODUCED với Julius và The Tempesst.
Lĩnh vực thứ 3 về dữ liệu địa lý được thể hiện bằng các mối quan hệ COUNTRY và CITY.
Từ đây càng thấy được sức mạnh của mơ hình bằng đồ thị. Cho phép chúng ta giải quyết các vấn đề phức tạp liên quan nhiều lĩnh vực như trong đời sống.
• Lưu ý : Những cái bẫy mơ hình hóa thường gặp
Mặc dù mơ hình hóa đồ thị có thể mơ tả những vấn đề rất phức tạp và đa miền nhưng chưa chắc một đồ thị cụ thể có thể phù hợp với mục đích của từng bài tốn. Thực tế thì cũng có những mơ hình sử dụng đồ thị nhưng khơng đem lại hiệu quả cao.
2.2.2Các phương pháp mơ hình hóa dữ liệu
2.2.2.1Mơ tả mơ hình bằng các thuật ngữ của ứng dụng
Chúng ta sử dụng các câu hỏi đối với dữ liệu để xác định các thực thể cũng như các mối quan hệ. Những câu chuyện của người dùng nhanh nhạy sẽ cung cấp phương tiện chính xác để thể hiện cái nhìn từ ngồi vào, từ trung tâm người dùng ra các nhu cầu của ứng dụng. Và các câu hỏi sẽ phát sinh trong quá trình đáp ứng nhu cầu này. Có thể xem xét ví dụ sau:
Là một người thích một quyển sách, tơi muốn biết những quyển sách nào mà những độc giả khác thích và giống như quyển sách mà tơi đã thích. Từ đó tơi có thể tìm được những quyển sách khác phù hợp để đọc.
Những dòng trên thể hiện được nhu cầu của người dùng, và cái nào thúc đẩy hình dạng và nội dung của mơ hình dữ liệu? Từ một cái nhìn về quan điểm mơ hình hóa dữ liệu, mệnh đề AS A (Là một) thiết lập bối cảnh gồm hai thực thể : một độc giả và một quyển sách và một mối quan hệ LIKES (thích) để kết nối giữa chúng. Mệnh đề I WANT (tôi muốn) đặt ra một câu hỏi : Những quyển sách nào được các độc giả khác thích mà họ cũng thích quyển sách mà tơi đang đọc? Câu hỏi này cho thấy có nhiều hơn mối quan hệ LIKES (thích) và nhiều thực thể hơn : các độc giả khác và các sách khác.
Những phân tích vừa rồi với các thực thể và các mối quan hệ được thể hiện trong mơ hình dữ liệu đơn giản sau :
Hình 2.10 Mơ hình dữ liệu bằng các thuật ngữ ứng dụng
Có thể thấy mơ hình trên sử dụng chính những gì thực tế ứng dụng phải làm được phục vụ nhu cầu của người dùng và nó trực tiếp mã hóa các câu hỏi của người dùng để mơ hình hóa dữ liệu.
2.2.2.2Các nút (node) đại diện cho các vật, các mối quan hệ (relationship) đại diện cho cấu trúc
Điều này có thể khơng đúng trong mọi trường hợp nhưng nhìn chung thì nó cũng là những chỉ dẫn thường gặp giúp chúng ta xác định khi nào thì sử dụng các nút, khi nào thì sử dụng các mối quan hệ.
- Sử dụng các nút để đại diện cho các thực thể - là những gì nằm trong mối quan tâm của vấn đề
- Sử dụng các mối quan hệ để thể hiện sự kết nối giữa các thực thể và để thiết lập các bối cảnh ngữ nghĩa cho mỗi thực thể, từ đó cấu trúc miền vấn đề.
- Sử dụng mối quan hệ trực tiếp để làm rõ hơn mối quan hệ ngữ nghĩa. Rất nhiều mối quan hệ là một chiều, đó là lý do tại sao các mối quan hệ trong đồ thị thuộc tính đều là quan hệ có hướng. Đối với những quan hệ hai chiều, khi thực hiện truy vấn cần chú ý bỏ qua hướng để đỡ phức tạp.
- Sử dụng các thuộc tính nút để đại diện cho các thuộc tính của thực thể, và cả bất kỳ siêu dữ liệu thực thể cần thiết nào, như nhãn thời gian, phiên bản..
- Sử dụng các thuộc tính của các mối quan hệ để thể hiện sức mạnh, trọng số hoặc chất lượng của một mối quan hệ và cả các siêu dữ liệu quan hệ cần thiết khác như nhãn thời gian, phiên bản..
Việc xác định cái nào là nút, cái nào là mối quan hệ rất quan trọng. Lưu ý rằng nếu đã là nút, thì nó sẽ phải có quan hệ với nhiều nút khác (hơn 2 nút) trong mạng. Và nếu đã là mối quan hệ thì nó phải có nút đầu, nút cuối và có liên quan tới hơn hai nút này. Giả sử ta sử dụng một mối quan hệ để mơ hình một thực thể như là một email x giữa user A và user B. Có thể dễ dàng thấy được mối quan hệ email này hồn tồn có thể có nhiều hơn sự kết nối giữa user A và user B. Từ đó ta lại phải có cách khắc phục là cấu trúc lại, mơ hình lại, chuyển mối quan hệ này thành một thực thể email x. Tuy nhiên trong thực tế nếu cứ phải phá vỡ mơ hình đã có trước đó thì ít nhiều cũng dẫn đến thay đổi các truy vấn hoặc các mã ứng dụng. Điều này sẽ gây tốn kém và ảnh hưởng tới sự tin tưởng của khách hàng.
2.2.2.3Các mối quan hệ chung và các mối quan hệ chi tiết
Khi thiết kế các loại quan hệ chúng ta nên chú ý tới sự chuyển đổi giữa sử dụng các nhãn quan hệ chi tiết với các mối quan hệ chung đủ điều kiện với các thuộc tính. Đó là sự khác biệt giữa việc sử dụng quan hệ DELIVERY_ADDRESS và HOME_ADDRESS với việc sử dụng quan hệ ADDRESS có thuộc tính {type:’delivery’} và {type:’home’}. Các mối quan hệ là những con đường quan trọng để đi vào đồ thị. Phân biệt bằng các kiểu quan hệ là cách tốt nhất để loại bỏ các mảng lớn của đồ thị từ một giao điểm. Sử dụng một hoặc nhiều giá trị thuộc tính để quyết định có hay khơng theo một mối quan hệ phát sinh thêm thủ tục vào-ra trong lần đầu tiên những thuộc tính đó được truy cập; bởi các thuộc tính nằm trong một tập tin được lưu trữ riêng biệt với các mối quan hệ (tuy nhiên, ở những lần sau thì chúng được lưu vào bộ đệm). Vì thế chúng ta nên sử dụng các mối quan hệ chi tiết khi mà ta có một tập kín các kiểu quan hệ. Và ngược lại, ta sử dụng các quan hệ chung với các thuộc tính trong các đồ thị đánh trọng số và có những u cầu như tìm đường đi ngắn nhất và khơng cần thiết phải là một tập kín các quan hệ.
Đơi khi chúng ta có thể có các tập kín của các mối quan hệ, nhưng trong một số trường hợp chúng ta muốn theo dõi các kiểu cụ thể của các mối quan hệ trong tập đó, trong khi mặt khác lại muốn theo dõi tất cả chúng, khơng phân biệt kiểu thì thế nào? Xét ví dụ cụ thể về các địa chỉ (Addresses). Theo nguyên tắc của tập kín, chúng ta có thể chọn để tạo các quan hệ HOME_ADDRESS, WORK_ADDRESS và DELIVERY_ADDRESS. Điều này cho phép chúng ta theo dõi các kiểu cụ thể của các quan hệ địa chỉ trong khi bỏ qua tất cả các quan hệ địa chỉ còn lại. Nhưng sẽ phải làm gì nếu tơi muốn tìm tất cả các địa chỉ cho một user? Có một vài giải pháp như sau. Cách 1, chúng ta có thể mã hóa tất cả các loại quan hệ address lại với nhau thành một loại chung là ADDRESS. Tuy nhiên, cách này sẽ trở nên khó sử dụng khi có nhiều loại mối quan hệ
khác nhau. Cách thứ 2 là chúng ta thêm vào một loại quan hệ ADDRESS vào mơ hình. Tức là mỗi nút đại diện cho một loại địa chỉ và nối với các user bằng 2 mối quan hệ : 1 quan hệ cụ thể (như là DELIVERY_ADDRESS) và 1 quan hệ chung ADDRESS (type: ‘delivery’).
2.2.2.4Mơ hình hóa các sự kiện
Khi hai hoặc nhiều thực thể khác nhau tương tác trong cùng một khoảng thời gian thì một sự kiện xuất hiện. Chúng ta có thể biểu diễn những sự kiện này bằng các node riêng, và kết nối với các thực thể tham gia sự kiện đó. Mơ hình hóa một sự kiện trong phạm vi các thuật ngữ của từng sản phẩm giống như một cấu trúc : một nút đại diện cho kết quả của sự tương tác giữa hai hoặc nhiều thực thể. Có thể sử dụng thuộc tính nhãn thời gian trong node trung gian này để biểu thị thời gian bắt đầu và kết thúc. Ví dụ sau sẽ chỉ rõ hơn các sự kiện và hành động được mơ hình hóa sử dụng các nút trung gian.
Hình 2.11 Mơ hình các sự kiện bằng các nút
Hình này mơ tả sự kiện Ian làm việc cho Neo với vai trò là engineer và bắt đầu làm việc vào ngày 1/5/2010
Trong Cypher thì được thể hiện như sau :
(ian)-[:EMPLOYMENT]->(employment)-[:EMPLOYER]->(neo), (employment)-[:ROLE]->(engineer)
2.2.2.5Các kiểu giá trị phức tạp
Các kiểu giá trị là những thứ khơng có sự xác định (định danh), ví dụ như tiền, địa chỉ, mã tồn kho… Xét cụ thể như địa chỉ, địa chỉ có thể là quốc gia, có thể là số nhà, đường phố.., có thể mã zip.. hoặc bao gồm tất cả. Đối với những kiểu giá trị phức tạp thế này, cách tốt nhất là biểu diễn chúng bằng các node riêng biệt.
2.2.2.6Thời gian
Thời gian có thể được mơ hình bằng nhiều cách trong đồ thị. Dưới đây sẽ giới thiệu hai kỹ thuật : cây thời gian và danh sách liên kết.
Cây thời gian :
Hình 2.12 Kỹ thuật cây thời gian
Cây thời gian này sẽ có thể chỉ ra ngày phát sóng của các tập của một chương trình TV nào đó. Từ đây có thể thấy kỹ thuật này dành cho việc tìm tất cả các sự kiện đã xảy ra trong một khoảng thời gian cụ thể nào đó.
Hình 2.13 Kỹ thuật danh sách liên kết
Nhiều sự kiện có các quan hệ tạm thời đối với các sự kiện trước và sau nó. Một sự kiện có thể là sự kiện trước một sự kiện nào đó, và ngược lại. Ở đây, chúng ta sử dụng mối quan hệ NEXT và PREVIOUS (hoặc tương đương thế) để tạo các danh sách liên kết để thấy được chuỗi sự kiện theo thời gian như ví dụ trên.
• Tạo phiên bản
Một đồ thị phiên bản có thể cho phép chúng ta khôi phục lại trạng thái trước đây của đồ thị tại một thời điểm nhất định. Đây là điều mà hầu hết các csdl đồ thị khơng hỗ trợ. Việc khơi phục lại là có thể, tuy nhiên để làm được điều đó, chúng ta phải tạo một sơ đồ bên trong mơ hình đồ thị mà trong đó các nút cũng như quan hệ đều được gán nhãn thời gian và được lưu trữ lại mỗi khi có thay đổi. Có thể thấy việc làm trên làm đồ thị phức tạp hơn nhiều cho việc truy vấn cũng như lưu trữ. Vì vậy mặc dù có thể nhưng hầu hết việc tạo phiên bản chỉ mang tính lý thuyết và tham khảo.
2.2.2.7 Phát triển theo vòng lặp và tăng tiến
Chúng ta phát triển mơ hình dữ liệu theo từng chức năng một và theo từng câu chuyện của người dùng. Điều này sẽ đảm bảo rằng chúng ta xác định các mối quan hệ của ứng dụng sẽ được sử dụng để truy vấn đồ thị. Một mơ hình dữ liệu được phát triển theo kiểu lặp và tăng tiến cung cấp bởi các chức năng của ứng dụng sẽ khá khác so với bằng việc rút ra bằng việc sử dụng phương pháp mơ hình dữ liệu đầu tiên, nhưng nó sẽ là một mơ hình đúng đắn hơn, được thúc đẩy bởi các nhu cầu cụ thể và các câu hỏi phát sinh trong các nhu cầu.
Csdl đồ thị cung cấp đầy đủ cho sự phát triển của mơ hình đồ thị một cách dễ dàng và linh hoạt. Rất hiếm khi phải di chuyển cũng như tiêu chuẩn hóa lại dữ liệu. Các sự kiện mới và thành phần mới có thể trở thành các nút và các quan hệ. Tuy nhiên có thể thêm các thành phần của đồ thị dễ dàng như vậy khơng có nghĩa là lúc nào chúng ta cũng sử dụng nó. Chúng ta sẽ ln phải xác định các thời điểm quan trọng để cấu trúc lại mơ hình như chúng ta mong muốn, và có thể sẽ qua rất nhiều lần. Ví dụ, khi ta đổi tên một
mối quan hệ đã tồn tại thì nó sẽ cho phép được sử dụng cho 2 nhu cầu. Khi những thời điểm đó phát sinh, chúng ta cũng nên nắm bắt chúng. Nếu ta đang phát triển giải pháp như là một cách thử nghiệm thì nó sẽ giống như một tín hiệu phù hợp của sự thử nghiệm hồi quy tại chỗ, cho phép chúng ta thực hiện các thay đổi đáng kể cho mơ hình với sự tự tin.
2.2.3Ngơn ngữ xử lý dữ liệu trong CSDL đồ thị
Như đã đề cập đến ở chương 1, một đồ thị thuộc tính gồm có các nút, các mối quan hệ và các thuộc tính. Và bất kể là nút hay quan hệ thì đều có thể có thuộc tính riêng. Mơ hình đồ thị thuộc tính cho phép chúng ta mơ tả bài tốn một cách tồn diện hơn, mơ tả được các bài tốn phức tạp và đúng với thực tế hơn. Tuy nhiên để sử dụng csdl đồ thị như vậy, chúng ta cần một ngôn ngữ truy vấn và thao tác với dữ liệu trên.
2.2.3.1Ngôn ngữ truy vấn đồ thị : tổng quan về Cypher
Cypher là ngôn ngữ truy vấn cho csdl đồ thị, có đặc điểm dễ đọc và dễ hiểu đối với cả các nhà phát triển, các chuyên gia csdl và các nhà kinh doanh.
Cypher cho phép người dùng tìm kiếm thơng tin trên csdl theo một mơ hình cụ thể nào đó.
Hình 2.14 Ngơn ngữ truy vấn Cypher
Trong ASCII tương đương với đồ thị trong Cypher, ta biểu diễn mối quan hệ trên như sau : (a)-[:KNOWS]->(b)-[:KNOWS]->(c), (a)-[:KNOWS]->(c)
Tuy nhiên cũng như hầu hết các ngôn ngữ khác, Cypher cũng có các câu lệnh riêng. Câu truy vấn đơn giản nhất bao gồm một mệnh đề START theo sau bởi MATCH và RETURN. Sau đây là một ví dụ đơn giản cho câu truy vấn sử dụng 3 mệnh đề trên để tìm bạn chung với người dùng có tên Michael.
START a=node:user(name= ‘Michael’)
MATCH (a)-[:KNOWS]->b –[:KNOWS]->(c), (a)-[:KNOWS]->(c) RETURN b,c
Chúng ta sẽ tìm hiểu các câu lệnh kỹ hơn.
START
START mô tả một hoặc nhiều điểm bắt đầu – có thể là các nút hoặc các mối quan hệ - trong đồ thị. Những điểm bắt đầu sẽ được chọn thơng qua tìm kiếm chỉ mục hoặc tìm kiếm trực tiếp dựa trên các nút và các mối quan hệ. Như ví dụ phía trên, điểm bắt đầu sẽ là điểm mà được đánh chỉ mục là user và có thuộc tính (khi đánh chỉ mục tạo nên) name có giá trị là Michael. Giá trị trả về từ việc tìm kiếm điểm này là điểm a (định danh a là do người dùng tự đặt). Định danh này được sử dụng từ đầu đến cuối truy vấn.
MATCH
Đây là phần đặc tả bằng ví dụ từng phần. Ta sử dụng các kí tự ASCII để đại diện cho các nút và các mối quan hệ, “vẽ” ra các dữ liệu mà chúng ta quan tâm.
Chúng ta sử dụng
- Dấu ngoặc đơn để vẽ các nút, như là : (a)
- Cặp dấu gạch ngang và lớn hơn/ nhỏ hơn để thể hiện mối quan hệ (có hướng từ gốc tới ngọn hoặc theo cả hai hướng), như là : -> và <-