2011-11-02 18 views
18

importowanie języka graph databases, rozumiećModel nieukierunkowany wykres w Rails?

  1. węzły (reprezentowane przez kółka)
  2. krawędzie (reprezentowanych przez strzałki) i
  3. właściwości (metadanych węzłów/krawędzi)

Graph Database Property Graph

graficzny (dzięki uprzejmości wikipedia) opisuje directed graph.

Jaki jest najlepszy sposób na modelowanie undirected graph w Railsach?

To znaczy wykres, na którym wszystkie krawędzie są wzajemne (jak podano graficznego) i gdzie właściwości każdej krawędzi są takie same, niezależnie od kierunku (przeciwnie powyżej graficznego).

Załóżmy domyślną konfigurację Rails 3 przy użyciu magazynu sql za pośrednictwem ActiveRecord.

Podwójny polymorphic association tworzyłby ukierunkowany wykres, zdolny do modelowania danych opisanych przez powyższy obraz.

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 

Jeżeli jedna przedłużyć ten model zarządzania odwrotne relacje, czy jest lepszy model dostępny?


Jednym z elementów aplikacji może być problemem wykres, ale to nie znaczy, że aplikacja jest wokół problemu, że kąty naprzemianległe wykres musi być wykonywane na danych, ani też, że zestaw danych jest większy niż dostępnej pamięci .

+2

Jeśli potrzebujesz wysokiej wydajności z dużymi wykresami, musisz popracować nad swoimi założeniami. Jest to złe dopasowanie dla (sql) RDBMS. –

+1

Złe dopasowanie do dużych wykresów? Absolutnie. Ale możliwe jednak. Zamiana lub modyfikowanie warstwy pamięci po początkowym prototypie, gdy jeden z nich będzie miał przykład prawdziwych danych, z którymi będziemy się zajmować, jest lepszy od początkowej dodanej złożoności w mojej książce. (wywołaj "optymalizację przedwczesną Knutha ...") –

+6

Prawidłowe wybory narzędzia i projektu to nie to samo co przedwczesna optymalizacja. Wiesz, jak bardzo dobrze używać młotka, i możesz napędzać śrubę młotkiem, ale to nie znaczy, że jest to najlepsze narzędzie do pracy. Przełączenie na śrubokręt w tym momencie nie jest przedwczesną optymalizacją. Jeśli masz zamiar potraktować ten projekt poważnie i jest czymś więcej niż zabawką, rozważania takie jak ta mają z góry sens. Jeśli jest to po prostu eksperyment, aby zobaczyć, jak dobrze relacyjna baza danych może przechowywać wykres, to też jest w porządku, ale dodajmy to do pytania, abyśmy wiedzieli, że to główny cel. – ctcherry

Odpowiedz

10

W undirected wykresu, jedyną rzeczą, którą musisz wiedzieć, jest to, czy węzeł jest podłączony do innego węzła. I nie ma czegoś takiego jak kierunek.

Proste podejście:

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 

ten nazywany jest również lista sąsiedztwa: dla każdego węzła możemy łatwo uzyskać listę sąsiednich (połączonych) węzłów.

Możliwy problem z tym podejściem: dwa razy przechowujemy połączenia. A jest podłączony do B i B jest podłączony do A.

Tak więc wydaje się, że lepiej znormalizować przechowywanie każdego połączenia tylko raz, a następnie będziemy naprawdę blisko oryginalnego wniosku.

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

Tylko że robimy, co w naszej mocy, aby nie narzucać żadnego nakazu lub kierunku poprzez nazwę.

Wyszukiwanie podłączonych węzłów to wszystkie węzły połączone jako node1 lub jako node2, co skutecznie pomija dowolny możliwy kierunek.

W tym przypadku należy również wyrazić potwierdzenie, że połączenie z (węzeł1, węzeł2) jest unikatowe, ale to (węzeł2, węzeł1) jest w rzeczywistości takie samo i nie może być wstawione dwukrotnie.

Mój osobisty wybór polegałby na używaniu drugiego schematu, chociaż utrzymanie pierwszego rozwiązania może być szybsze (patrz również: question).

Znalazłem również bardzo interesujący article, w którym autor wyjaśnia, w jaki sposób wykresy mogą być przechowywane w bazie danych. Bardzo głęboki, ale bardziej skoncentrowany na bazie danych.

Mam nadzieję, że to pomoże.

+0

Zgadzam się, że chcę przechowywać połączenia/krawędzie tylko raz w bazie danych, więc wolę twój drugi przykład. Ale jak wyglądałaby moja klasa Node w tym przykładzie? Wygląda na to, że związek active_nord jest zawsze skierowany, czyż nie? – NobodysNightmare

+0

węzeł1.connections przyniesie węzeł2. ale node2.connections nic nie da. @nathanvda –

+0

Nie pokazałem, jak go zaimplementować (ale opisałem to: poszukaj wszystkich węzłów połączonych jako 'węzeł1' lub' węzeł2'). Wygląda na to, że szukasz tylko jednego rodzaju? Zadaj kolejne pytanie, na którym możesz pokazać, co wypróbowałeś i co dzieje się źle, i umieść link tutaj, a ja się obejrzę. – nathanvda

3

Zamiast polimorficzne skojarzenia, spróbuj użyć has_many: poprzez

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 

można przechowywać właściwości krawędzi int modelu członkostwa.

+0

Według mojego zrozumienia, has_many through utworzyłoby efektywny niekierowany wykres z dodatkiem 'add_index: memberships, [: group_id,: person_id], unique: true' w migracji kosztem niekontrolowanego rozłożenia tabel. Próba precyzyjnego modelowania diagramu, w twoim przykładzie potrzebna jest dodatkowa tabela, aby obsłużyć samoodnawialny "know" edge na klasie Person. –

2
+1

Rozpatrywanie [baz danych wykresu] (http://en.wikipedia.org/wiki/Graph_database) to pierwszy link w pytaniu, załóżmy, że ludzie przeczytali [obie] (http://stackoverflow.com/questions/3689182/ przy opracowywaniu aplikacji internetowych-kiedy-chcesz-używać-wykresu-bazy danych-kontra-zrobić) preexisting [posty] (http://stackoverflow.com/questions/5896288/rails-3-and bazy danych). To pytanie powstało dzięki mojemu własnemu prototypowaniu, a IMHO wyłuszcza bazę danych wykresów, kiedy pisanie pierwszych linii kodu jest przesadzone. Jeśli się nie zgadzasz, wyjaśnienie zostanie * bardzo * docenione. –

+0

Całkowicie przegapiłem punkt "używanie sql store". GDB są dobrym rozwiązaniem dla tych zadań, ponieważ zapewniają dobrą wydajność chodzenia łącza i zapytania.Jeśli nie są przewidziane żadne poważne obciążenia lub długie spacery, dołącz do tabeli z dodatkowymi polami to również dobre rozwiązanie. –

+0

Dla małego wykresu zachowaj go w pamięci i przechowuj jako blob, jeśli wymagana jest trwałość. W przypadku dużego wykresu wystarczy policzyć liczbę potrzebnych dostępu do dysku. RDBMS łączy zabicie wydajności. –

Powiązane problemy