2011-11-02 36 views
18

Nhập ngôn ngữ của graph databases, hiểuTạo mô hình đồ thị vô hướng trong Rails?

  1. nút (đại diện bởi vòng tròn),
  2. cạnh (đại diện bởi mũi tên), và
  3. tính (siêu dữ liệu của các nút/cạnh)

Graph Database Property Graph

Các đồ họa (biếu không của wikipedia) mô tả một directed graph.

Cách tốt nhất để tạo mô hình undirected graph trong Rails là gì?

Đó là để nói, một biểu đồ mà tất cả các cạnh là đối ứng (như trong trên đồ họa), và nơi các thuộc tính của mỗi cạnh đều giống nhau bất kể hướng (trái với trên đồ họa).

Giả sử thiết lập Rails 3 mặc định bằng cách sử dụng cửa hàng sql thông qua ActiveRecord.

Một đôi polymorphic association sẽ tạo biểu đồ có hướng, có thể mô hình dữ liệu được mô tả bằng hình ảnh trên.

def Edge < ActiveRecord::Base 
    belongs_to :head, polymorphic: true 
    belongs_to :tail, polymorphic: true 
end 

class Node < ActiveRecord::Base 
    has_many :from, as: :head 
    has_many :to, as: :tail 
end 

class Group < ActiveRecord::Base 
    # a Node of Type: Group 
    has_many :from, as: :head 
    has_many :to, as: :tail 
end 

Có nên mở rộng mô hình này để quản lý các mối quan hệ nghịch đảo hoặc mô hình tốt hơn không?


Một yếu tố của một ứng dụng có thể là một vấn đề đồ thị, nhưng nó không có nghĩa là ứng dụng tập trung vào các vấn đề, rằng transversals đồ thị phải được thực hiện trên các dữ liệu, cũng không phải là các tập dữ liệu lớn hơn bộ nhớ còn trống .

+2

Nếu bạn cần hiệu suất cao với biểu đồ lớn, Bạn cần phải làm việc trên các giả định của mình. Đây là một sự phù hợp không tốt đối với RDBMS (sql). –

+1

Phù hợp với đồ thị lớn không phù hợp? Chắc chắn rồi. Nhưng dù sao thì cũng có thể. Trao đổi hoặc sửa đổi một tầng lưu trữ sau một nguyên mẫu ban đầu khi một ví dụ có một ví dụ về dữ liệu thực sẽ được xử lý là thích hợp hơn với độ phức tạp ban đầu được thêm vào trong cuốn sách của tôi. (gọi Knuth "tối ưu hóa sớm ...") –

+6

Lựa chọn công cụ và thiết kế đúng không giống như tối ưu hóa sớm. Bạn biết làm thế nào để sử dụng một cái búa thực sự tốt, và bạn có thể lái một cái đinh vít bằng một cái búa, nhưng điều đó không có nghĩa nó là công cụ tốt nhất cho công việc. Chuyển sang một tuốc nơ vít tại thời điểm này không phải là một tối ưu hóa sớm. Nếu bạn dự định thực hiện dự án này một cách nghiêm túc, và nó không chỉ là một món đồ chơi, thì những cân nhắc như thế này làm cho toàn bộ ý nghĩa trả trước. Nếu đây chỉ là một thử nghiệm để xem cơ sở dữ liệu quan hệ có thể lưu trữ một đồ thị tốt như thế nào thì cũng không sao, nhưng hãy thêm nó vào câu hỏi để chúng ta biết đó là ý định chính. – ctcherry

Trả lời

10

Trong một đồ thị vô hướng, điều duy nhất bạn cần phải biết, là liệu một nút được kết nối với một nút khác. Và không có thứ gì như một hướng.

cách tiếp cận đơn giản:

class Node 
    has_many :connected_nodes 
    has_many :nodes, :through => :connected_nodes 
end 

class ConnectedNode 
    belongs_to :node 
    belongs_to :connected_node, :class_name => 'Node' 
end 

này cũng được gọi là một danh sách kề: cho mỗi nút chúng ta có thể dễ dàng có được danh sách các liền kề nút (kết nối).

Có thể có vấn đề với cách tiếp cận này: chúng tôi lưu trữ các kết nối hai lần. A được kết nối với B và B được kết nối với A.

Vì vậy, có vẻ bình thường hơn để lưu trữ từng kết nối chỉ một lần và sau đó chúng tôi thực sự gần với đề xuất ban đầu của bạn.

class Connection 
    belongs_to :node1, :class_name => 'Node' 
    belongs_to :node2, :clasS_name => 'Node' 
end 

Chỉ chúng tôi làm hết sức mình để không áp đặt bất kỳ thứ tự hoặc hướng nào thông qua đặt tên.

Truy xuất các nút được kết nối là tất cả các nút được kết nối với dạng node1 hoặc là node2, do đó có thể bỏ qua bất kỳ hướng nào có thể có hiệu quả. Trong trường hợp này, bạn cũng cần phải thể hiện xác nhận rằng kết nối với (node1, node2) là duy nhất, nhưng (node2, node1) thực sự giống nhau và không thể chèn hai lần.

Lựa chọn cá nhân của tôi sẽ là sử dụng lược đồ thứ hai, mặc dù việc duy trì giải pháp đầu tiên có thể nhanh hơn (xem thêm question) này.

Tôi cũng tìm thấy một địa chỉ article rất thú vị, nơi tác giả giải thích cách biểu đồ có thể được lưu trữ trong cơ sở dữ liệu. Rất sâu sắc, nhưng có nhiều cơ sở dữ liệu hơn.

Hy vọng điều này sẽ hữu ích.

+0

Tôi đồng ý rằng tôi chỉ muốn lưu trữ các kết nối/cạnh một lần trong cơ sở dữ liệu, vì vậy tôi thích ví dụ thứ hai của bạn. Nhưng lớp Node của tôi sẽ trông như thế nào trong ví dụ này? Dường như mối quan hệ has_many của ActiveRecord luôn được hướng dẫn, phải không? – NobodysNightmare

+0

node1.connections sẽ mang lại node2. nhưng node2.connections sẽ không mang lại bất cứ điều gì. @nathanvda –

+0

Tôi không cho thấy cách triển khai nó (nhưng mô tả nó: tìm tất cả các nút được kết nối dưới dạng 'node1' hoặc là' node2'). Có vẻ như bạn chỉ tìm kiếm một loại? Vui lòng đặt một câu hỏi khác, nơi bạn có thể hiển thị những gì bạn đã thử và những gì đang xảy ra và đặt liên kết ở đây và tôi sẽ xem xét. – nathanvda

3

Thay vì sử dụng các hiệp hội đa hình, hãy thử sử dụng has_many,: thông qua

class Group < ActiveRecord::Base 
    has_many :memberships 
    has_many :persons, :through => :memberships 
end 

class Membership < ActiveRecord::Base 
    belongs_to :group 
    belongs_to :person 
end 

class Person < ActiveRecord::Base 
    has_many :memberships 
    has_many :groups, :through => :memberships 
end 

Bạn có thể lưu trữ các thuộc tính của cạnh int mô hình thành viên.

+0

Theo hiểu biết của tôi, một has_many thông qua sẽ tạo ra một đồ thị vô hướng hiệu quả với việc bổ sung một 'add_index: Memberships, [: group_id,: person_id], unique: true' trong quá trình di chuyển với chi phí của bảng sprawl. Cố gắng mô hình chính xác sơ đồ, một bảng bổ sung là cần thiết trong ví dụ của bạn để xử lý cạnh 'know' tự tham chiếu trên lớp Person. –

2
+1

Xem xét [cơ sở dữ liệu biểu đồ] (http://en.wikipedia.org/wiki/Graph_database) là liên kết đầu tiên trong câu hỏi, giả sử mọi người đã đọc [cả hai] (http://stackoverflow.com/questions/3689182/ khi-phát triển-web-ứng dụng-khi-sẽ-bạn-sử dụng-một-đồ thị-cơ sở dữ liệu-so-a-do) từ trước [bài viết] (http://stackoverflow.com/questions/5896288/rails-3-and -graph-databases). Câu hỏi này nảy sinh thông qua việc tạo mẫu của riêng tôi, và IMHO phá vỡ một cơ sở dữ liệu đồ thị khi viết các dòng mã đầu tiên là quá mức cần thiết. Nếu bạn không đồng ý, một lời giải thích sẽ được * rất nhiều * đánh giá cao. –

+0

Tôi hoàn toàn bỏ lỡ điểm 'sử dụng cửa hàng sql'. GDB là giải pháp tốt cho các tác vụ này vì chúng cung cấp hiệu suất và truy vấn liên kết tốt.Nếu không có tải trọng nghiêm trọng hoặc đi bộ liên kết dài được dự định, tham gia bảng với các lĩnh vực bổ sung là một giải pháp tốt cũng có. –

+0

Đối với một biểu đồ nhỏ, chỉ cần giữ nó trong bộ nhớ và lưu nó dưới dạng blob nếu cần thiết. Đối với một đồ thị lớn, chỉ cần đếm số lượng truy cập đĩa cần thiết. RDBMS tham gia giết hiệu suất. –

Các vấn đề liên quan