Tagi a system ekspercki

0

Tworzę coś w rodzaju słownika w dziedzinie historii. Każda informacja (obiekt) jest opisana zestawem tagów. Pomiędzy tagami występują powiązania - nazwijmy je "relacje", a każda "relacja" tagu ma określony typ.
Przykład: Bóg A w mitologii jakiegoś państwa jest rodzicem Boga B; relacja zatem nazywałaby się: "rodzic".

Próbuję rozwiązać następującą kwestię techniczną:

Baza danych składa się z tagów-obiektów ("Bóg A", "Bóg B", "Kraj A", "Kraj Z" itd.). Każdy obiekt posiada jakieś relacje z innymi obiektami, np. obiekt "Bóg A", relacja "Wyznawany w", obiekt "Kraj C".

Problem: czy da się zaprojektować tabelę (lub tabele) opisującą powiązania między tagami tak, by nie tworzyć ani redundantnych danych ani nie tworzyć tworów typu tabela: [Tag1 ID, Tag2 ID, Relacja] (nazwy pól). Problem polega na tym, że baza tagów nie ma właściwie hierarchicznej struktury (choć powyższy przykład to może sugerować: że "Kraj" jest wyżej w hierarchii od "Boga" - ale nie we wszystkich tagach sytuacja jest taka oczywista). Stąd wypytując bazę o rodzaje relacji, które zawiera jakiś tag, musielibyśmy wykonywać w powyższym przypadku dwa razy zapytanie: najpierw po Tag1 ID, następnie po Tag2 ID (uważam, że nie ma sensu robić procedury typu lista pozwoleń: te tagi można wpisywać do pola Tag1, a tamte do Tag2 - tym bardziej, że lista tagów jest potencjalnie nieskończona i otwarta, tzn. użytkownik może dopisać w każdej chwili nowy Tag i stworzyć nowe relacje pomiędzy nimi).

Chodzi zatem o większą zgrabność projektu tabeli relacji pomiędzy tagami - tak, aby tagi (będące generalnie w stosunku do siebie w strukturze płaskiej) były przejrzyście umieszczone w tabeli, by nie było niejednoznaczności, czy umieszczać dany tag w polu Tag1 czy Tag2 (choć w sumie nie ma to znaczenia dla działania bazy danych, jeśli byśmy - jak napisałem wyżej - dwukrotnie odpytywali tabelę najpierw po polu Tag1, a potem Tag2). Czyli o likwidację tworu: Tag1 i Tag2 w tabeli relacji pomiędzy nimi.

Macie jakiś pomysł? Z góry dzięki.

0

Tabela Tagi jest sama z sobą w relacji wiele-do-wielu, więc bez dodatkowej tabeli przejściowej się nie obejdzie (takiej jak napisałeś tag1, tag2, relacja).

Stąd wypytując bazę o rodzaje relacji, które zawiera jakiś tag, musielibyśmy wykonywać w powyższym przypadku dwa razy zapytanie: najpierw po Tag1 ID, następnie po Tag2 ID

Czyli nie za dużo wiesz o bazach danych i języku sql.
select * from RelacjeTagów where Relacja="xyz" and (tag1="foo" or tab2="foo") i nie ważne jest czy foo jest jako tag1 czy jako tag2

by nie było niejednoznaczności, czy umieszczać dany tag w polu Tag1 czy Tag2

Kwestia interfejsu użytkownika. On nie musi wiedzieć jak to jest po stronie bazy danych składowane.

dwukrotnie odpytywali tabelę najpierw po polu Tag1, a potem Tag2

Nie wiem o co chodzi?

select * from RelacjeTagów RT
inner join Tagi T1 on RT.Tag1Id=T1.Id
inner join Tagi T2 on RT.Tag2Id=T2.Id
inner join Relacje R on RT.RelacjaId=R.Id

jedno zapytanie i masz wszystkie informacje o tagu 1 i 2 oraz o relacji między nimi

żeby nie mieć pól Tag1 i Tag2 można posługiwać się nieco bardziej skomplikowaną strukturą

Tagi
Id
Nazwa

Relacje
Id
Nazwa

RelacjeTagów
Id
RelacjaId

RelacjeTagówTagi
RelacjaTagówId
TagId

W RelacjeTagówTagi możesz mieć dowolną liczbę tagów, które są w relacji RelacjaId z tabeli RelacjeTagów. Na poziomie kodu aplikacji ograniczasz możliwość tworzenia relacji tylko pomiędzy dwoma tagami.

1 użytkowników online, w tym zalogowanych: 0, gości: 1