{"id":30139,"date":"2019-11-26T10:08:32","date_gmt":"2019-11-26T09:08:32","guid":{"rendered":"https:\/\/nearshore-it.eu\/artykuly\/neo4j-zaproszenie-do-grafowych-baz-danych\/"},"modified":"2024-10-03T16:56:31","modified_gmt":"2024-10-03T14:56:31","slug":"neo4j-zaproszenie-do-grafowych-baz-danych","status":"publish","type":"post","link":"https:\/\/nearshore-it.eu\/pl\/artykuly\/neo4j-zaproszenie-do-grafowych-baz-danych\/","title":{"rendered":"Neo4j \u2013 zaproszenie do grafowych baz danych"},"content":{"rendered":"\n<div class=\"table-of-contents\">\n    <p class=\"title\">Id\u017a do:<\/p>\n    <ol>\n                    <li><a href=\"#Czym-jest-grafowa-baza-danych-?\">1.  Czym jest grafowa baza danych?<\/a><\/li>\n                    <li><a href=\"#Wyb\u00f3r-bazy-danych\">2.  Wyb\u00f3r bazy danych<\/a><\/li>\n                    <li><a href=\"#Zalety-Neo4j\">3.  Zalety Neo4j<\/a><\/li>\n                    <li><a href=\"#Co-to-znaczy-\u017ce-Neo4j-jest-baz\u0105-NoSQLow\u0105-?\">4.  Co to znaczy, \u017ce Neo4j jest baz\u0105 NoSQLow\u0105?<\/a><\/li>\n                    <li><a href=\"#Wyszukiwarka-po\u0142\u0105cze\u0144-autobusowych-case-study\">5.  Wyszukiwarka po\u0142\u0105cze\u0144 autobusowych \u2013 case study<\/a><\/li>\n                    <li><a href=\"#K\u0142opotliwy-RDBMS\">6.  K\u0142opotliwy RDBMS<\/a><\/li>\n                    <li><a href=\"#RDBMS-pe\u0142ne-Join\u00f3w\">7.  RDBMS pe\u0142ne Join\u00f3w<\/a><\/li>\n                    <li><a href=\"#RDBMS-pe\u0142ne-podzapyta\u0144\">8.  RDBMS pe\u0142ne podzapyta\u0144<\/a><\/li>\n                    <li><a href=\"#Case-study-u\u017cycie-grafu-Neo4j\">9.  Case study: u\u017cycie grafu Neo4j<\/a><\/li>\n                    <li><a href=\"#Podsumowanie\">10.  Podsumowanie<\/a><\/li>\n            <\/ol>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"Czym-jest-grafowa-baza-danych-?\">Czym jest grafowa baza danych?<\/h2>\n\n\n\n<p>Neo4j (<a href=\"https:\/\/neo4j.com\/\" target=\"_blank\" rel=\"noopener\">https:\/\/neo4j.com\/<\/a>) jest jedn\u0105 z najpopularniejszych, o ile nie najpopularniejsz\u0105 grafow\u0105 baz\u0105 danych. Dla przypomnienia i uporz\u0105dkowania wiedzy: <strong>graf jest kompozycj\u0105 dw\u00f3ch typ\u00f3w element\u00f3w, jakimi s\u0105 w\u0119z\u0142y i relacje<\/strong>. W\u0119ze\u0142 mo\u017ce reprezentowa\u0107 okre\u015blony typ lub kilka typ\u00f3w i posiada swoje w\u0142a\u015bciwo\u015bci (ang. properties). Relacje za\u015b poza nazw\u0105 i w\u0142asnymi w\u0142a\u015bciwo\u015bciami posiadaj\u0105 \u2013 co najistotniejsze \u2013 kierunek oddzia\u0142ywania. Wspomniane w\u0142a\u015bciwo\u015bci s\u0105 kolekcjami par klucz \u2013 warto\u015b\u0107. S\u0142u\u017c\u0105 do przechowywania istotnych informacji. Dla przyk\u0142adu: je\u017celi w\u0119z\u0142em b\u0119dzie osoba, to jej w\u0142a\u015bciwo\u015bciami mog\u0105 by\u0107: imi\u0119, nazwisko, wiek albo lista ulubionych ksi\u0105\u017cek.<\/p>\n\n\n\n<p>Relacje mi\u0119dzy w\u0119z\u0142ami w Neo4j \u2013 jak i w grafowych bazach danych w og\u00f3le \u2013 s\u0105 tak samo wa\u017cnymi danymi jak w\u0119z\u0142y. Traktujemy je jak obiekty, kt\u00f3rych istnienie jest determinowane przez obecno\u015b\u0107 danych w\u0119z\u0142\u00f3w. Wyst\u0119powanie relacji samodzielne nie ma \u017cadnego uzasadnienia.<\/p>\n\n\n\n<p>Relacje znane z baz danych typu RDBMS (Relational Database Management System) zazwyczaj b\u0119d\u0105 nam si\u0119 kojarzy\u0107 z oznaczaniem danych w jakim\u015b wierszu z jednej tabeli jako maj\u0105cych swoje odzwierciedlenie w konkretnym wierszu innej tabeli. Pozwoli nam to na operacje kaskadowe podczas edycji lub usuwania danych. Podczas normalizowania modelu danych w RDBMS mo\u017cemy si\u0119 zetkn\u0105\u0107 z konieczno\u015bci\u0105 wprowadzenia specjalnych tabel po\u015brednicz\u0105cych mi\u0119dzy dwoma tabelami s\u0142u\u017c\u0105cymi do wi\u0105zania ze sob\u0105 ca\u0142ych grup wierszy. <\/p>\n\n\n\n<p><strong>Czytaj tak\u017ce: <a href=\"https:\/\/nearshore-it.eu\/pl\/artykuly\/test-driven-development-na-co-dzien\/\">Poznaj korzy\u015bci Test-Driven Development na co dzie\u0144<\/a><\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Wyb\u00f3r-bazy-danych\">Wyb\u00f3r bazy danych<\/h2>\n\n\n\n<p>Wci\u0105\u017c jeszcze w wielu \u015brodowiskach panowa\u0107 mo\u017ce prze\u015bwiadczenie, \u017ce RDBMS s\u0105 najlepsze do wszelkiego rodzaju zada\u0144. Osoby decyzyjne w zakresie doboru baz danych mog\u0105 nieprzychylnie spogl\u0105da\u0107 na alternatywne rozwi\u0105zania do przechowywania danych, a za tak\u0105 zwyk\u0142o si\u0119 dot\u0105d uwa\u017ca\u0107 w\u0142a\u015bnie Neo4j. <strong>Jak rozs\u0105dnie dokona\u0107 wyboru bazy lub baz danych do wykorzystania w projekcie? Przede wszystkim wyb\u00f3r powinien by\u0107 zdeterminowany przez stoj\u0105ce przed aplikacj\u0105 zadania. <\/strong><\/p>\n\n\n\n<p>Ju\u017c na etapie projektowania aplikacji, jeszcze na etapie wyboru bazy danych, warto zastanowi\u0107 si\u0119 nad kilkoma kwestiami:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>jakie operacje b\u0119d\u0105 w przysz\u0142o\u015bci wykonywane na gromadzonych danych?<\/li>\n\n\n\n<li>czy zadaniem aplikacji b\u0119dzie zapisywanie i odczytywanie danych bez \u017cadnych bardziej skomplikowanych operacji?<\/li>\n\n\n\n<li>mo\u017ce najistotniejsze b\u0119d\u0105 wzajemne relacje mi\u0119dzy danymi, a program powinien pomaga\u0107 w ich analizie?<\/li>\n<\/ul>\n\n\n\n<p>Wyb\u00f3r bazy uzale\u017cniony jest wi\u0119c od tego, jaka jest podstawowa funkcja projektowanej aplikacji i charakter danych. Czy b\u0119d\u0105 to dane os\u00f3b zatrudnionych w konkretnej organizacji, wsp\u00f3\u0142tworz\u0105cych jej struktur\u0119 organizacyjn\u0105, a aplikacja, kt\u00f3r\u0105 tworzysz, b\u0119dzie s\u0142u\u017cy\u0107 do zapewnienia sprawnego obiegu dokument\u00f3w mi\u0119dzy pracownikami? <strong>Mo\u017ce masz do opracowania wyszukiwark\u0119 po\u0142\u0105cze\u0144 lotniczych? Albo aplikacj\u0119, kt\u00f3ra zapewni wsparcie logistyczne dla firmy transportowej? A mo\u017ce dosta\u0142e\u015b supertajne zlecenie dla rz\u0105dowych s\u0142u\u017cb specjalnych polegaj\u0105ce na zaimplementowaniu systemu wspieraj\u0105cego zarz\u0105dzanie siatk\u0105 agent\u00f3w i informator\u00f3w?<\/strong> W ostatnim przyk\u0142adzie rzeczywi\u015bcie fantazja nieco mnie ponios\u0142a, ale g\u0142\u00f3wnie dlatego, \u017ce mo\u017cliwo\u015bci, jakich dostarcza nam grafowa baza danych, s\u0105 naprawd\u0119 ogromne.<\/p>\n\n\n\n<p>Jednak nie zawsze przestrzega si\u0119 zasady dopasowania bazy danych do celu aplikacji, a zwolennicy nowych i cz\u0119sto bardziej odpowiednich rozwi\u0105za\u0144 musz\u0105 zmaga\u0107 si\u0119 ze sceptycyzmem manager\u00f3w (\u201ePrzecie\u017c nikt nie korzysta z tych rozwi\u0105za\u0144\u201d).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Zalety-Neo4j\">Zalety Neo4j<\/h2>\n\n\n\n<p>Jakie wielkie musi by\u0107 zaskoczenie i zdumienie oponent\u00f3w, gdy po wej\u015bciu na stron\u0119 g\u0142\u00f3wn\u0105 projektu Neo4j ich oczom ukazuj\u0105 si\u0119 liczne logotypy \u015bwiatowych marek czy instytucji rz\u0105dowych albo badawczych. Od firm medycznych, przez instytuty naukowo-badawcze, po firmy finansowe, transportowe, telekomunikacyjne i wojskowe. Pe\u0142na obszerna lista oraz case studies dost\u0119pne s\u0105 <a href=\"https:\/\/neo4j.com\/\" target=\"_blank\" rel=\"noopener\">na stronie projektu.<\/a> To smakowity k\u0105sek dla wszystkich zajmuj\u0105cych si\u0119 analiz\u0105 i modelowaniem danych oraz architekt\u00f3w aplikacji.<\/p>\n\n\n\n<p>Jak wida\u0107, popularno\u015b\u0107 Neo4j i grafowych baz danych ci\u0105gle ro\u015bnie.<strong> W wielu rankingach, w tym w moim prywatnym, baza danych Neo4j jest jednym z lider\u00f3w takich rozwi\u0105za\u0144.<\/strong> Warto wspomnie\u0107 o tym, \u017ce tw\u00f3rcy Neo4j zadbali o przyjazne zorganizowanie Clusteringu i pracy w chmurze, a najcz\u0119\u015bciej stosowanym rozwi\u0105zaniem jest Neo4j pracuj\u0105cy na AWS \u2013 co r\u00f3wnie\u017c przemawia na jej korzy\u015b\u0107.<\/p>\n\n\n\n<p>Warto pami\u0119ta\u0107, \u017ce jako narz\u0119dzie Neo4j jest mocno wspierane zar\u00f3wno przez wsp\u00f3\u0142czesne narz\u0119dzia do pisania kodu, jak i popularne frameworki, na przyk\u0142ad Spring Framework w projekcie \u201e<a href=\"https:\/\/spring.io\/projects\/spring-data-neo4j\" target=\"_blank\" rel=\"noopener\">Spring Data Neo4j<\/a>\u201d. To, \u017ce grafowa baza danych jest tak intensywnie rozwijana, dobrze wr\u00f3\u017cy na przysz\u0142o\u015b\u0107.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Co-to-znaczy-\u017ce-Neo4j-jest-baz\u0105-NoSQLow\u0105-?\">Co to znaczy, \u017ce Neo4j jest baz\u0105 NoSQLow\u0105?<\/h2>\n\n\n\n<p>Tak jak bazy danych z grupy RDBMS korzystaj\u0105 z j\u0119zyka zapyta\u0144 SQL, tak Neo4j korzysta z j\u0119zyka Cypher. W obu przypadkach s\u0105 to j\u0119zyki deklaratywne. O ile sk\u0142adniowo Cypher jest w wielu aspektach podobny do SQL, o tyle jedn\u0105 z najcz\u0119\u015bciej wskazywanych r\u00f3\u017cnic jest u\u017cycie s\u0142owa kluczowego <strong>MATCH<\/strong> w miejsce <strong>SELECT<\/strong>. &nbsp;Inn\u0105 jest wykorzystanie \u2013 w znaczeniu dos\u0142ownym \u2013 strza\u0142ek relacji.<\/p>\n\n\n\n<p>Cypher to j\u0119zyk bardzo elastyczny pod wzgl\u0119dem mo\u017cliwo\u015bci budowania zapyta\u0144. Wida\u0107 to dobrze cho\u0107by w takich przyk\u0142adach jak ten, gdzie przeprowadzamy dopasowanie warunkowe. W SQL zawsze warunek umie\u015bcimy w klauzuli <strong>WHERE<\/strong>, za\u015b w Cypher dodatkowo mo\u017ce zosta\u0107 zawarty ju\u017c podczas deklaracji w\u0119z\u0142a. Mo\u017cemy tworzy\u0107 interesuj\u0105ce i przydatne zapytania z\u0142o\u017cone z etap\u00f3w przy wykorzystaniu klauzuli <strong>WITH<\/strong>.<\/p>\n\n\n\n<p>Bardzo wa\u017cna, a cz\u0119sto nawet kluczowa, jest czytelno\u015b\u0107 zapyta\u0144, kt\u00f3r\u0105 tu odnajdujemy. Godna uwagi jest r\u00f3wnie\u017c \u0142atwo\u015b\u0107 pisania zapyta\u0144 dla os\u00f3b, kt\u00f3re maj\u0105 zrozumienie poj\u0119cia grafu i zetkn\u0119\u0142y si\u0119 z pisowni\u0105 zapyta\u0144 w SQL.<\/p>\n\n\n<div class=\"special-content-box style-1\">\r\n    <div class=\"box\">\r\n                <div class=\"content\">\r\n                                <\/div>\r\n    <\/div>\r\n<\/div>\r\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Wyszukiwarka-po\u0142\u0105cze\u0144-autobusowych-case-study\">Wyszukiwarka po\u0142\u0105cze\u0144 autobusowych \u2013 case study<\/h2>\n\n\n\n<p>Zaprezentowany przeze mnie ni\u017cej przyk\u0142ad aplikacji do rezerwacji bilet\u00f3w zaczerpni\u0119ty zosta\u0142 z \u017cycia. Problem, z kt\u00f3rym si\u0119 mierzy\u0142em, zaistnia\u0142 kilka lat temu, g\u0142\u00f3wnie przez przywi\u0105zanie os\u00f3b decyzyjnych do rozwi\u0105za\u0144 uznanych za sprawdzone i niech\u0119ci do rozeznania w gronie developerskim w poszukiwaniu nowych mo\u017cliwo\u015bci.<\/p>\n\n\n\n<p><strong>Projekt:<\/strong> aplikacja, kt\u00f3ra s\u0142u\u017cy do rezerwacji bilet\u00f3w autobusowych.<\/p>\n\n\n\n<p><strong>Produkt ko\u0144cowy:<\/strong> rezerwacja miejsca i zakup biletu. Z racji zbyt du\u017cej z\u0142o\u017cono\u015bci tematu ograniczmy si\u0119 jednak wy\u0142\u0105cznie do wyszukiwarki po\u0142\u0105cze\u0144.<\/p>\n\n\n\n<p><strong>Dzia\u0142anie aplikacji:<\/strong> zanim u\u017cytkownik zarezerwuje bilet, powinien najpierw wskaza\u0107 przystanek, z kt\u00f3rego zechce odjecha\u0107, oraz przystanek docelowy z listy dost\u0119pnych.<\/p>\n\n\n\n<p><strong>Modelowanie:<\/strong> w podej\u015bciu zgodnym z RDBMS do zamodelowania tego obszaru b\u0119dziemy potrzebowa\u0107 przynajmniej trzech tabel. Pierwsz\u0105 b\u0119dzie rejestr przystank\u00f3w, drug\u0105 \u2013 rejestr tras, na kt\u00f3rych zlokalizowane s\u0105 przystanki. W trzeciej tabeli do konkretnych tras przypiszemy poszczeg\u00f3lne przystanki.<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_1.png\" alt=\"Schemat tabel i relacji zgodny z RDBMS\" class=\"wp-image-24954\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Rysunek 1. Schemat tabel i relacji zgodny z RDBMS<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"K\u0142opotliwy-RDBMS\">K\u0142opotliwy RDBMS<\/h2>\n\n\n\n<p>Warto zwr\u00f3ci\u0107 uwag\u0119 na pewien typowy problem tabeli z odwzorowanymi relacjami pomi\u0119dzy poszczeg\u00f3lnymi wierszami spajanych tabel. Wyst\u0119puj\u0105ce w niej wiersze zawieraj\u0105 kom\u00f3rki wype\u0142nione nieczytelnymi liczbami nale\u017c\u0105cymi zwykle do indeksowanych kluczy g\u0142\u00f3wnych tabel w relacji. Rozszyfrowywanie pochodzenia i znaczenia tych numer\u00f3w mo\u017ce niekiedy wymaga\u0107 sporego wysi\u0142ku. Tym wi\u0119kszego, im bardziej z\u0142o\u017cona jest tabela. W naszym przyk\u0142adzie taka spajaj\u0105ca tabela mog\u0142aby wygl\u0105da\u0107 na przyk\u0142ad tak:<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_2.png\" alt=\"Tabela Neo4j\" class=\"wp-image-24955\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Tabela 1. Przyk\u0142adowy fragment mo\u017cliwej zawarto\u015bci tabeli 'track_bus_stop\u2019<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Takie \u201etwory\u201d znajdziemy w relacjach typu \u201eMany-to-Many\u201d. Mog\u0105 by\u0107 one szczeg\u00f3lnie uci\u0105\u017cliwe, gdy w projekcie jest sporo tabel, zdefiniowanych kluczy obcych i relacji.<strong> S\u0105 te\u017c problematyczne, gdy istnieje ca\u0142a masa danych w skryptach potrzebnych do zasilania testowych instancji baz danych w celu integracyjnej weryfikacji poprawno\u015bci implementacji.<\/strong> Sytuacja cz\u0119sto kluczowa w developmencie. Nierzadko trzeba si\u0119 solidnie napracowa\u0107, \u017ceby przygotowa\u0107 nowe rekordy danych z zachowaniem relacji do tabel po\u015brednicz\u0105cych. Dane w wierszach musz\u0105 by\u0107 unikalne albo dopasowane do wzorca, zgodne z innymi danymi \u201enienullowymi\u201d z co najmniej dziesi\u0119ciu innych tabel. Mo\u017ce si\u0119 zdarzy\u0107 tak, \u017ce w modelu danych zaczynaj\u0105 \u2013 np. przez nieuwag\u0119 \u2013 pojawia\u0107 si\u0119 odwo\u0142ania cykliczne. W\u00f3wczas bez wykonania operacji wy\u0142\u0105czenia wszystkich ogranicze\u0144 na bazie, nie jest mo\u017cliwe ani dalsze dodawanie nowych danych, ani nawet zaimportowanie do niej prawid\u0142owych danych.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"RDBMS-pe\u0142ne-Join\u00f3w\">RDBMS pe\u0142ne Join\u00f3w<\/h2>\n\n\n\n<p>Przejd\u017amy do pierwszego kroku przy u\u017cyciu wyszukiwarki po\u0142\u0105cze\u0144. B\u0119dzie to wyszukiwanie przez pasa\u017cera wszystkich mo\u017cliwych tras przypisanych do wybranego przystanku.<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_3.png\" alt=\"Neo4j schemat\" class=\"wp-image-24956\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Listing 1. Zapytanie w SQL do wyszukania nazw wszystkich tras, do kt\u00f3rych nale\u017cy przyk\u0142adowy przystanek \u201ePstr\u0105gowa\u201d<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Co interesuj\u0105cego w\u0142a\u015bnie si\u0119 sta\u0142o? <strong>Dane z trzech osobnych tabel na tym etapie scali\u0142y si\u0119 w zapytaniu w jedn\u0105 i mo\u017cemy wybra\u0107 z niej te wiersze, kt\u00f3re zawieraj\u0105 szukany przystanek.<\/strong> Je\u017celi jedn\u0105 tras\u0119 okre\u015bla nam N sk\u0142adaj\u0105cych si\u0119 na ni\u0105 przystank\u00f3w po\u0142\u0105czonych z ni\u0105 nazwami tras, to odrzucamy wszystkie wiersze, w kt\u00f3rych przypisany przystanek jest inny ni\u017c wskazany przez nas.<\/p>\n\n\n\n<p>Poni\u017cej przyk\u0142ad tabeli wynikowej przed okrojeniem jej z wierszy o innej nazwie przystanku ni\u017c zadany:<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_4.png\" alt=\"Tabela przedstawiaj\u0105ca zbi\u00f3r najwa\u017cniejszych danych z tabel tras i przystank\u00f3w zestawionych ze sob\u0105 za po\u015brednictwem tabeli &#039;track_bus_stop&#039;\" class=\"wp-image-24957\" style=\"width:1068px;height:813px\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Tabela 2. Tabela przedstawiaj\u0105ca zbi\u00f3r najwa\u017cniejszych danych z tabel tras i przystank\u00f3w zestawionych ze sob\u0105 za po\u015brednictwem tabeli 'track_bus_stop&#8217;<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:2px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Po odrzuceniu wierszy, w kt\u00f3rych nazwa przystanku nie odpowiada wskazanej przez nas, otrzymujemy taki oto zbi\u00f3r wierszy, kt\u00f3ry nast\u0119pnie nale\u017cy odpowiednio przyci\u0105\u0107 poprzez odrzucenie ewentualnych powt\u00f3rze\u0144.<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_5.png\" alt=\"Neo4j grafika\" class=\"wp-image-24958\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Tabela 3. Zbi\u00f3r unikalnych nazw tras, do kt\u00f3rych nale\u017cy wskazany przystanek<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"RDBMS-pe\u0142ne-podzapyta\u0144\">RDBMS pe\u0142ne podzapyta\u0144<\/h2>\n\n\n\n<p>Wyobra\u017amy sobie, \u017ce teraz nasz pasa\u017cer potrzebuje listy wszystkich przystank\u00f3w, do kt\u00f3rych b\u0119dzie m\u00f3g\u0142 dojecha\u0107, wsiadaj\u0105c do autobusu na wskazanym przystanku. Poni\u017cej przyk\u0142adowe zapytanie b\u0119d\u0105ce odpowiedzi\u0105 na oczekiwanie u\u017cytkownika aplikacji.<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_6.png\" alt=\"Neo4j listing\" class=\"wp-image-24959\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Listing 2. Przyk\u0142adowe zapytanie zwracaj\u0105ce list\u0119 unikalnych przystank\u00f3w, do kt\u00f3rych mo\u017cna dojecha\u0107 z przystanku X<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>W powy\u017cszym zapytaniu mamy do czynienia z konieczno\u015bci\u0105 u\u017cycia dw\u00f3ch podzapyta\u0144 na rzecz jednej operacji projekcji. Wyst\u0119puje \u0142\u0105cznie sze\u015b\u0107 operacji \u0142\u0105czenia tabel przy u\u017cyciu polecenia JOIN.<strong> Z\u0142o\u017cono\u015b\u0107 tego zapytania jest jego niew\u0105tpliw\u0105 wad\u0105. Inn\u0105 wad\u0105 jest brak intuicyjno\u015bci w konstrukcji powsta\u0142ych w j\u0119zyku SQL w przypadku, gdy chcemy uzyska\u0107 wycinek zbioru danych badanej rzeczywisto\u015bci.<\/strong> Wynikiem zapytania w naszym przyk\u0142adzie b\u0119dzie zbi\u00f3r danych zawartych w tabeli poni\u017cej.<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_7.png\" alt=\"Neo4j tabela \" class=\"wp-image-24960\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Tabela 4. Przyk\u0142adowy zbi\u00f3r wynikowy mo\u017cliwych przystank\u00f3w, do kt\u00f3rych u\u017cytkownik odjedzie z podanego przystanku pocz\u0105tkowego<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Zapytania z obu poprzednich listing\u00f3w to dopiero wst\u0119p do pozosta\u0142ych operacji prowadz\u0105cych do kupna biletu. Kolejne zapytania b\u0119d\u0105 niekiedy jeszcze bardziej z\u0142o\u017cone. Szczeg\u00f3lnie gdy utworzymy dodatkowe tabele do przechowywania informacji o cenach bilet\u00f3w uzale\u017cnionych od wybranego przystanku odjazdu oraz przystanku docelowego, rodzaju trasy, kursu, pory nocnej albo np. okresowych zni\u017cek na danych odcinkach przejazdu.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Case-study-u\u017cycie-grafu-Neo4j\">Case study: u\u017cycie grafu Neo4j<\/h2>\n\n\n\n<p>Sp\u00f3jrzmy na analizowany model danych przez pryzmat obiekt\u00f3w grafu. Co to oznacza, \u017ce co\u015b da si\u0119 opisa\u0107 przy pomocy grafu? Jak pisa\u0142em na pocz\u0105tku: graf to zbi\u00f3r w\u0119z\u0142\u00f3w i ich wzajemnych skierowanych relacji. W kontek\u015bcie analizowanej wyszukiwarki po\u0142\u0105cze\u0144 autobusowych nasze przyk\u0142adowe w\u0119z\u0142y i relacje mo\u017cemy z wykorzystaniem Neo4j przedstawi\u0107 w taki spos\u00f3b:<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_8-1.png\" alt=\"Graf obrazuj\u0105cy przystanki jako w\u0119z\u0142y i ich wzajemne zdefiniowane relacje\" class=\"wp-image-24969\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Rysunek 2. Graf obrazuj\u0105cy przystanki jako w\u0119z\u0142y i ich wzajemne zdefiniowane relacje<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Przystanki s\u0105 w\u0119z\u0142ami, a droga, kt\u00f3ra prowadzi od jednego do drugiego przystanku, w spos\u00f3b naturalny okre\u015bla istniej\u0105c\u0105 mi\u0119dzy nimi relacj\u0119. Droga pomi\u0119dzy przystankami spowoduje wyst\u0105pienie odpowiednich tras przejazdu, wi\u0119c potraktujemy tras\u0119 jako w\u0142a\u015bciwo\u015b\u0107 relacji przez ni\u0105 wyznaczon\u0105.<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_9.png\" alt=\"Neo4j listing \" class=\"wp-image-24962\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Listing 3. Zapytanie w Cypher s\u0142u\u017c\u0105ce do wyszukania wszystkich tras, do kt\u00f3rych przypisany zosta\u0142 wskazany przystanek<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Przyk\u0142adowy rezultat powy\u017cszego zapytania:<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_10.png\" alt=\"Neo4j tabela\" class=\"wp-image-24963\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Tabela 5. Przyk\u0142adowy rezultat zapytania s\u0142u\u017c\u0105cego do wyszukania wszystkich tras, do kt\u00f3rych przynale\u017cy wskazany przystanek<\/em><\/figcaption><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Zapytanie z listingu 3 ju\u017c na pierwszy rzut oka jest o wiele bardziej intuicyjne, ni\u017c mia\u0142o to miejsce w przypadku SQL. Na pewno jest te\u017c mniej skomplikowane. W powy\u017cszym zapytaniu staramy si\u0119 wybra\u0107 wszystkie relacje typu <strong>LEADS TO<\/strong> &nbsp;do innych przystank\u00f3w, a wychodz\u0105ce z takiego, kt\u00f3rego nazwa odpowiada przystankowi wskazanemu w zapytaniu. Po czym zwracamy ich trasy przy u\u017cyciu s\u0142owa kluczowego <strong>RETURN<\/strong>.<\/p>\n\n\n\n<p>Przejd\u017amy do kroku drugiego, kt\u00f3ry powinien wykona\u0107 u\u017cytkownik, by uzyska\u0107 list\u0119 mo\u017cliwych przystank\u00f3w, przez kt\u00f3re b\u0119dzie przeje\u017cd\u017ca\u0142 autobus. W Neo4j uzyskamy j\u0105, wykonuj\u0105c na przyk\u0142ad takie zapytanie jak na listingu 4.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_11.png\" alt=\"Neo4j listing\" class=\"wp-image-24964\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Listing 4. Zapytanie zwracaj\u0105ce nazwy wszystkich przystank\u00f3w, do kt\u00f3rych mo\u017cliwe b\u0119dzie dotarcie z tego wskazanego przez u\u017cytkownika<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Powy\u017csze zapytanie mo\u017cemy odczyta\u0107 nast\u0119puj\u0105co: <strong>\u201eSkoro mi\u0119dzy wskazanym przystankiem a kolejnymi istnieje relacja \u0142\u0105cz\u0105cej je drogi, to zwr\u00f3\u0107 mi wszystkie kolejne a\u017c do ostatniego\u201d<\/strong><\/p>\n\n\n\n<p>Poni\u017cej przyk\u0142adowy rezultat w postaci grafu oraz w postaci tabeli nazw:<\/p>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_12.png\" alt=\"Graf prezentuj\u0105cy mo\u017cliwe docelowe przystanki wraz z ich wzajemnymi relacjami\" class=\"wp-image-24965\" style=\"width:1200px;height:273px\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Rysunek 3. Graf prezentuj\u0105cy mo\u017cliwe docelowe przystanki wraz z ich wzajemnymi relacjami<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/28.10_graphic_13.png\" alt=\"Zbi\u00f3r nazw w\u0119z\u0142\u00f3w z powy\u017cszego zapytania o mo\u017cliwe docelowe przystanki\" class=\"wp-image-24966\" title=\"\"><figcaption class=\"wp-element-caption\"><em>Tabela 6. Zbi\u00f3r nazw w\u0119z\u0142\u00f3w z powy\u017cszego zapytania o mo\u017cliwe docelowe przystanki<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Jak widzimy w powy\u017cszych przyk\u0142adach, zapytania w Cypher s\u0105 du\u017co kr\u00f3tsze ni\u017c ich odpowiedniki w SQL i zaprezentowane w odpowiednich listingach SQL. Jednocze\u015bnie pozwalaj\u0105 uzyska\u0107 identyczne efekty. Dodatkow\u0105 zalet\u0105 jest to, \u017ce w Neo4j poza widokiem tabelarycznym dost\u0119pny jest r\u00f3wnie\u017c widok w\u0119z\u0142\u00f3w i ich relacji.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Podsumowanie\">Podsumowanie<\/h2>\n\n\n\n<p>Je\u017celi wycinek rzeczywisto\u015bci, nad kt\u00f3rym pracujemy, stanowi zbi\u00f3r obiekt\u00f3w i ich wzajemnych relacji \u2013 bardzo prawdopodobne, \u017ce odnajdziemy tam struktur\u0119 grafow\u0105 i u\u017cycie grafowej bazy danych b\u0119dzie mia\u0142o sens. W niniejszym tek\u015bcie chcia\u0142em zaprezentowa\u0107 przede wszystkim intuicyjno\u015b\u0107 i \u0142atwo\u015b\u0107 w konstruowaniu zapyta\u0144 w Neo4j. Poda\u0142em przyk\u0142ad aplikacji, w kt\u00f3rej mierzy\u0142em si\u0119 z problemem niedopasowania narz\u0119dzia do potrzeb projektu. Gdybym w\u00f3wczas posiada\u0142 obecne do\u015bwiadczenie i wiedz\u0119 na temat grafowych baz danych, stara\u0142bym si\u0119 przekona\u0107 decyzyjne osoby w projekcie do zastosowania Neo4j. Uchroni\u0142oby to klienta przed wieloma niepotrzebnymi problemami i wydatkami.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Popularno\u015b\u0107 grafowych baz danych ci\u0105gle ro\u015bnie. Jak jednak dokona\u0107 wyboru bazy danych i czy grafowe bazy sprawdz\u0105 si\u0119 w ka\u017cdym projekcie? W dzisiejszym artykule chcia\u0142bym przyjrze\u0107 si\u0119 zaletom grafowych baz danych i zach\u0119ci\u0107 mo\u017cliwie jak najwi\u0119cej os\u00f3b z bran\u017cy programistycznej do korzystania z wszelkich dobrodziejstw, jakie mog\u0105 wnie\u015b\u0107 do codziennej pracy developera. Skupi\u0119 si\u0119 szczeg\u00f3lnie na moim ulubionym reprezentancie tego gatunku, kt\u00f3rym jest Neo4j.<\/p>\n","protected":false},"author":121,"featured_media":25112,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"iawp_total_views":225,"footnotes":""},"categories":[1,582],"tags":[571],"offering":[],"class_list":["post-30139","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-artykuly","category-technologie","tag-nosql-pl"],"acf":[],"_links":{"self":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/30139","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/users\/121"}],"replies":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/comments?post=30139"}],"version-history":[{"count":2,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/30139\/revisions"}],"predecessor-version":[{"id":33221,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/30139\/revisions\/33221"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/media\/25112"}],"wp:attachment":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/media?parent=30139"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/categories?post=30139"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/tags?post=30139"},{"taxonomy":"offering","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/offering?post=30139"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}