From d8bebb0f2cb48326f45b85702b9df214a1537eb0 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Tue, 13 Aug 2024 23:57:50 +0300 Subject: [PATCH] Tabs (#55) * add jekyll-tabs --- .wordlist.txt | 1 + Gemfile | 6 + Gemfile.lock | 310 ++++++++++++++++++++++++++++++++++++++++++ README.md | 15 ++ _config.yml | 1 + _layouts/default.html | 3 + assets/css/tabs.css | 55 ++++++++ assets/js/tabs.js | 5 + index.md | 10 ++ path_algorithm.md | 68 ++++----- 10 files changed, 440 insertions(+), 34 deletions(-) create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 assets/css/tabs.css create mode 100644 assets/js/tabs.js diff --git a/.wordlist.txt b/.wordlist.txt index 9e8c5b7..16e44ae 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -117,6 +117,7 @@ dockerfile duplications dups endNode +endtab endtabs entrypoint enum diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..4a156f9 --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +group :jekyll_plugins do + gem 'github-pages' + gem 'jekyll-tabs' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..5af0882 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,310 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (7.2.0) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + base64 (0.2.0) + bigdecimal (3.1.8) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.12.2) + colorator (1.1.0) + commonmarker (0.23.10) + concurrent-ruby (1.3.4) + connection_pool (2.4.1) + csv (3.3.0) + dnsruby (1.72.2) + simpleidn (~> 0.2.1) + drb (2.2.1) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + ethon (0.16.0) + ffi (>= 1.15.0) + eventmachine (1.2.7) + execjs (2.9.1) + faraday (2.10.1) + faraday-net_http (>= 2.0, < 3.2) + logger + faraday-net_http (3.1.1) + net-http + ffi (1.17.0-aarch64-linux-gnu) + ffi (1.17.0-aarch64-linux-musl) + ffi (1.17.0-arm-linux-gnu) + ffi (1.17.0-arm-linux-musl) + ffi (1.17.0-arm64-darwin) + ffi (1.17.0-x86-linux-gnu) + ffi (1.17.0-x86-linux-musl) + ffi (1.17.0-x86_64-darwin) + ffi (1.17.0-x86_64-linux-gnu) + ffi (1.17.0-x86_64-linux-musl) + forwardable-extended (2.6.0) + gemoji (4.1.0) + github-pages (232) + github-pages-health-check (= 1.18.2) + jekyll (= 3.10.0) + jekyll-avatar (= 0.8.0) + jekyll-coffeescript (= 1.2.2) + jekyll-commonmark-ghpages (= 0.5.1) + jekyll-default-layout (= 0.1.5) + jekyll-feed (= 0.17.0) + jekyll-gist (= 1.5.0) + jekyll-github-metadata (= 2.16.1) + jekyll-include-cache (= 0.2.1) + jekyll-mentions (= 1.6.0) + jekyll-optional-front-matter (= 0.3.2) + jekyll-paginate (= 1.1.0) + jekyll-readme-index (= 0.3.0) + jekyll-redirect-from (= 0.16.0) + jekyll-relative-links (= 0.6.1) + jekyll-remote-theme (= 0.4.3) + jekyll-sass-converter (= 1.5.2) + jekyll-seo-tag (= 2.8.0) + jekyll-sitemap (= 1.4.0) + jekyll-swiss (= 1.0.0) + jekyll-theme-architect (= 0.2.0) + jekyll-theme-cayman (= 0.2.0) + jekyll-theme-dinky (= 0.2.0) + jekyll-theme-hacker (= 0.2.0) + jekyll-theme-leap-day (= 0.2.0) + jekyll-theme-merlot (= 0.2.0) + jekyll-theme-midnight (= 0.2.0) + jekyll-theme-minimal (= 0.2.0) + jekyll-theme-modernist (= 0.2.0) + jekyll-theme-primer (= 0.6.0) + jekyll-theme-slate (= 0.2.0) + jekyll-theme-tactile (= 0.2.0) + jekyll-theme-time-machine (= 0.2.0) + jekyll-titles-from-headings (= 0.5.3) + jemoji (= 0.13.0) + kramdown (= 2.4.0) + kramdown-parser-gfm (= 1.1.0) + liquid (= 4.0.4) + mercenary (~> 0.3) + minima (= 2.5.1) + nokogiri (>= 1.16.2, < 2.0) + rouge (= 3.30.0) + terminal-table (~> 1.4) + webrick (~> 1.8) + github-pages-health-check (1.18.2) + addressable (~> 2.3) + dnsruby (~> 1.60) + octokit (>= 4, < 8) + public_suffix (>= 3.0, < 6.0) + typhoeus (~> 1.3) + html-pipeline (2.14.3) + activesupport (>= 2) + nokogiri (>= 1.4) + http_parser.rb (0.8.0) + i18n (1.14.5) + concurrent-ruby (~> 1.0) + jekyll (3.10.0) + addressable (~> 2.4) + colorator (~> 1.0) + csv (~> 3.0) + em-websocket (~> 0.5) + i18n (>= 0.7, < 2) + jekyll-sass-converter (~> 1.0) + jekyll-watch (~> 2.0) + kramdown (>= 1.17, < 3) + liquid (~> 4.0) + mercenary (~> 0.3.3) + pathutil (~> 0.9) + rouge (>= 1.7, < 4) + safe_yaml (~> 1.0) + webrick (>= 1.0) + jekyll-avatar (0.8.0) + jekyll (>= 3.0, < 5.0) + jekyll-coffeescript (1.2.2) + coffee-script (~> 2.2) + coffee-script-source (~> 1.12) + jekyll-commonmark (1.4.0) + commonmarker (~> 0.22) + jekyll-commonmark-ghpages (0.5.1) + commonmarker (>= 0.23.7, < 1.1.0) + jekyll (>= 3.9, < 4.0) + jekyll-commonmark (~> 1.4.0) + rouge (>= 2.0, < 5.0) + jekyll-default-layout (0.1.5) + jekyll (>= 3.0, < 5.0) + jekyll-feed (0.17.0) + jekyll (>= 3.7, < 5.0) + jekyll-gist (1.5.0) + octokit (~> 4.2) + jekyll-github-metadata (2.16.1) + jekyll (>= 3.4, < 5.0) + octokit (>= 4, < 7, != 4.4.0) + jekyll-include-cache (0.2.1) + jekyll (>= 3.7, < 5.0) + jekyll-mentions (1.6.0) + html-pipeline (~> 2.3) + jekyll (>= 3.7, < 5.0) + jekyll-optional-front-matter (0.3.2) + jekyll (>= 3.0, < 5.0) + jekyll-paginate (1.1.0) + jekyll-readme-index (0.3.0) + jekyll (>= 3.0, < 5.0) + jekyll-redirect-from (0.16.0) + jekyll (>= 3.3, < 5.0) + jekyll-relative-links (0.6.1) + jekyll (>= 3.3, < 5.0) + jekyll-remote-theme (0.4.3) + addressable (~> 2.0) + jekyll (>= 3.5, < 5.0) + jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) + rubyzip (>= 1.3.0, < 3.0) + jekyll-sass-converter (1.5.2) + sass (~> 3.4) + jekyll-seo-tag (2.8.0) + jekyll (>= 3.8, < 5.0) + jekyll-sitemap (1.4.0) + jekyll (>= 3.7, < 5.0) + jekyll-swiss (1.0.0) + jekyll-tabs (1.2.1) + jekyll (>= 3.0, < 5.0) + jekyll-theme-architect (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-cayman (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-dinky (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-hacker (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-leap-day (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-merlot (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-midnight (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-minimal (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-modernist (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-primer (0.6.0) + jekyll (> 3.5, < 5.0) + jekyll-github-metadata (~> 2.9) + jekyll-seo-tag (~> 2.0) + jekyll-theme-slate (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-tactile (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-time-machine (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-titles-from-headings (0.5.3) + jekyll (>= 3.3, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + jemoji (0.13.0) + gemoji (>= 3, < 5) + html-pipeline (~> 2.2) + jekyll (>= 3.0, < 5.0) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.4) + listen (3.9.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + logger (1.6.0) + mercenary (0.3.6) + minima (2.5.1) + jekyll (>= 3.5, < 5.0) + jekyll-feed (~> 0.9) + jekyll-seo-tag (~> 2.1) + minitest (5.24.1) + net-http (0.4.1) + uri + nokogiri (1.16.7-aarch64-linux) + racc (~> 1.4) + nokogiri (1.16.7-arm-linux) + racc (~> 1.4) + nokogiri (1.16.7-arm64-darwin) + racc (~> 1.4) + nokogiri (1.16.7-x86-linux) + racc (~> 1.4) + nokogiri (1.16.7-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.16.7-x86_64-linux) + racc (~> 1.4) + octokit (4.25.1) + faraday (>= 1, < 3) + sawyer (~> 0.9) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (5.1.1) + racc (1.8.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) + rexml (3.3.5) + strscan + rouge (3.30.0) + rubyzip (2.3.2) + safe_yaml (1.0.5) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sawyer (0.9.2) + addressable (>= 2.3.5) + faraday (>= 0.17.3, < 3) + securerandom (0.3.1) + simpleidn (0.2.3) + strscan (3.1.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + typhoeus (1.4.1) + ethon (>= 0.9.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (1.8.0) + uri (0.13.0) + webrick (1.8.1) + +PLATFORMS + aarch64-linux + aarch64-linux-gnu + aarch64-linux-musl + arm-linux + arm-linux-gnu + arm-linux-musl + arm64-darwin + x86-linux + x86-linux-gnu + x86-linux-musl + x86_64-darwin + x86_64-linux + x86_64-linux-musl + +DEPENDENCIES + github-pages + jekyll-tabs + +BUNDLED WITH + 2.5.17 diff --git a/README.md b/README.md index 5075b51..f1f5633 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,18 @@ # https://docs.falkordb.com + + + +# Build + +```bash +bundle install +bundle exec jekyll build +``` + +# Run + +```bash +bundle exec jekyll serve +``` \ No newline at end of file diff --git a/_config.yml b/_config.yml index 993909b..a0d8b82 100644 --- a/_config.yml +++ b/_config.yml @@ -20,4 +20,5 @@ aux_links_new_tab: true plugins: - jekyll-sitemap + - jekyll-tabs diff --git a/_layouts/default.html b/_layouts/default.html index 923c1c1..9553ddd 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -7,6 +7,7 @@ {% include head.html %} + Skip to main content {% include icons/icons.html %} {% include components/sidebar.html %} @@ -37,5 +38,7 @@ {% if site.mermaid %} {% include components/mermaid.html %} {% endif %} + + diff --git a/assets/css/tabs.css b/assets/css/tabs.css new file mode 100644 index 0000000..017847d --- /dev/null +++ b/assets/css/tabs.css @@ -0,0 +1,55 @@ +ul.tab { + display: flex; + flex-wrap: wrap; + margin-left: -20px; + padding: 0; + list-style: none; + position: relative; +} + +ul.tab > * { + flex: none; + padding-left: 20px; + position: relative; +} + +ul.tab > * > a { + display: block; + text-align: center; + padding: 9px 20px; + color: #999; + border-bottom: 2px solid transparent; + border-bottom-color: transparent; + font-size: 12px; + text-transform: uppercase; + transition: color .1s ease-in-out; + line-height: 20px; +} + +ul.tab > .active > a { + border-color: #1e87f0; +} + +ul.tab > li > a { + text-decoration: none; + cursor: pointer; +} +ul.tab > li::before, +ul.tab-content > li::before { + content: none; /* Remove any content added by ::before */ +} + +ul.tab-content { + padding: 0; +} + +ul.tab-content > li { + display: none; +} +ul.tab-content > li.active { + display: block; +} + +ul.tab-content > li::before { + content: none; /* Remove any content added by ::before */ +} \ No newline at end of file diff --git a/assets/js/tabs.js b/assets/js/tabs.js new file mode 100644 index 0000000..86b51e5 --- /dev/null +++ b/assets/js/tabs.js @@ -0,0 +1,5 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.jekyllTabs=t():e.jekyllTabs=t()}(self,(()=>(()=>{"use strict";var e={973:(e,t,o)=>{o.r(t),o.d(t,{addClass:()=>r,createElementFromHTML:()=>s,findElementsWithTextContent:()=>n,getChildPosition:()=>a});const a=e=>{const t=e.parentNode;for(let o=0;o{const o=document.querySelectorAll(e),a=[];for(let e=0;e{const t=document.createElement("template");return t.innerHTML=e.trim(),t.content.firstChild},r=(e,t,o)=>{e.className=e.className?`${e.className} ${t}`:t,setTimeout((()=>{e.className=e.className.replace(t,"").trim()}),o)}},39:(e,t,o)=>{o.r(t),o.d(t,{activateTabFromUrl:()=>d,addCopyToClipboardButtons:()=>u,appendToastMessageHTML:()=>b,copyToClipboard:()=>c,handleTabClicked:()=>i,removeActiveClasses:()=>l,syncTabsWithSameLabels:()=>y,updateUrlWithActiveTab:()=>p});const{getChildPosition:a,createElementFromHTML:n,findElementsWithTextContent:s,addClass:r}=o(973),l=e=>{const t=e.querySelectorAll("ul > li");Array.prototype.forEach.call(t,(e=>{e.classList.remove("active")}))},i=e=>{const t=e.parentNode,o=t.parentNode,n=a(t);if(t.className.includes("active"))return;const s=o.getAttribute("data-tab");if(!s)return;const r=document.getElementById(s);l(o),l(r),r.querySelectorAll("ul.tab-content > li")[n].classList.add("active"),t.classList.add("active")},c=(e,t)=>{if(navigator.clipboard&&window.isSecureContext)navigator.clipboard.writeText(e);else{const t=document.createElement("textarea");t.value=e,t.style.position="absolute",t.style.left="-999999px",document.body.prepend(t),t.select();try{document.execCommand("copy")}catch(e){console.error(e)}finally{t.remove()}}"function"==typeof t&&t()},d=()=>{var e;const t=null===(e=window.location.hash)||void 0===e?void 0:e.substring(1);if(!t)return;const o=document.getElementById(t);if(!o)return;const a=new URLSearchParams(window.location.search).get("active_tab");if(!a)return;const n=o.querySelector("li#"+a+" > a");n&&i(n)},p=e=>{const t=e.parentNode,o=t.parentNode,a=new URLSearchParams(window.location.search);a.set("active_tab",t.id);const n=window.location.pathname+"?"+a.toString()+"#"+o.id;history.replaceState(null,"",n)},u=({buttonHTML:e,showToastMessageOnCopy:t,toastDuration:o})=>{const a=document.querySelectorAll("ul.tab-content > li pre");for(let s=0;s{m(o)}),i.addEventListener("click",(()=>{c(r.innerText,d)}))}},b=e=>{const t=document.createElement("div");t.id="jekyll-tabs-copy-to-clipboard-message",t.textContent=e,document.getElementsByTagName("body")[0].appendChild(t)},m=e=>{r(document.getElementById("jekyll-tabs-copy-to-clipboard-message"),"show",e)},y=e=>{const t=s("a",e.textContent);for(let o=0;o{for(var a in t)o.o(t,a)&&!o.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var a={};return(()=>{o.r(a),o.d(a,{init:()=>i});const{activateTabFromUrl:e,updateUrlWithActiveTab:t,handleTabClicked:n,addCopyToClipboardButtons:s,syncTabsWithSameLabels:r,appendToastMessageHTML:l}=o(39),i=(o={})=>{const a={syncTabsWithSameLabels:!1,activateTabFromUrl:!1,addCopyToClipboardButtons:!1,copyToClipboardSettings:{buttonHTML:"",showToastMessageOnCopy:!1,toastMessage:"Code copied to clipboard",toastDuration:3e3}},i=Object.assign(Object.assign(Object.assign({},a),o),{copyToClipboardSettings:Object.assign(Object.assign({},a.copyToClipboardSettings),o.copyToClipboardSettings)}),c=document.querySelectorAll("ul.tab > li > a");if(Array.prototype.forEach.call(c,(e=>{e.addEventListener("click",(o=>{o.preventDefault(),n(e),i.activateTabFromUrl&&t(e),i.syncTabsWithSameLabels&&r(e)}),!1)})),i.addCopyToClipboardButtons){const e=i.copyToClipboardSettings;s(e),e.showToastMessageOnCopy&&l(e.toastMessage)}i.activateTabFromUrl&&e()}})(),a})())); + +window.addEventListener('load', function () { + jekyllTabs.init(); +}); diff --git a/index.md b/index.md index 53fe8d4..2d91566 100644 --- a/index.md +++ b/index.md @@ -37,6 +37,9 @@ Once loaded you can interact with FalkorDB using any of the supported [client li Here we'll use [FalkorDB Python client](https://pypi.org/project/FalkorDB/) to create a small graph representing a subset of motorcycle riders and teams taking part in the MotoGP league, once created we'll start querying our data. +{% tabs started %} + +{% tab started python %} ```python from falkordb import FalkorDB @@ -65,6 +68,13 @@ res = g.query("""MATCH (r:Rider)-[:rides]->(t:Team {name:'Ducati'}) RETURN count print(res.result_set[0][0]) # Prints: 1 ``` +{% endtab %} + +{% endtabs %} + + + + For additional demos please see visit [Demos](https://github.com/FalkorDB/demos). diff --git a/path_algorithm.md b/path_algorithm.md index 9e16f80..43e5edb 100644 --- a/path_algorithm.md +++ b/path_algorithm.md @@ -32,15 +32,15 @@ This graph represents a road network with 7 cities (A, B, C, and so on) and 11 o Let's create the graph. -{{< highlight bash >}} +```bash GRAPH.QUERY g "CREATE (a:City{name:'A'}), (b:City{name:'B'}), (c:City{name:'C'}), (d:City{name:'D'}), (e:City{name:'E'}), (f:City{name:'F'}), (g:City{name:'G'}), (a)-[:Road{time:4, dist:3}]->(b), (a)-[:Road{time:3, dist:8}]->(c), (a)-[:Road{time:4, dist:2}]->(d), (b)-[:Road{time:5, dist:7}]->(e), (b)-[:Road{time:5, dist:5}]->(d), (d)-[:Road{time:4, dist:5}]->(e), (c)-[:Road{time:3, dist:6}]->(f), (d)-[:Road{time:1, dist:4}]->(c), (d)-[:Road{time:2, dist:12}]->(f), (e)-[:Road{time:5, dist:5}]->(g), (f)-[:Road{time:4, dist:2}]->(g)" - {{< / highlight >}} + ``` If you're using RedisInsight v2, you can create and visualize the graph by slightly modifying the above query: you'll have to assign aliases to all nodes and relationships, and return them: -{{< highlight bash >}} +```bash GRAPH.QUERY g "CREATE (a:City{name:'A'}), (b:City{name:'B'}), (c:City{name:'C'}), (d:City{name:'D'}), (e:City{name:'E'}), (f:City{name:'F'}), (g:City{name:'G'}), (a)-[r1:Road{time:4, dist:3}]->(b), (a)-[r2:Road{time:3, dist:8}]->(c), (a)-[r3:Road{time:4, dist:2}]->(d), (b)-[r4:Road{time:5, dist:7}]->(e), (b)-[r5:Road{time:5, dist:5}]->(d), (d)-[r6:Road{time:4, dist:5}]->(e), (c)-[r7:Road{time:3, dist:6}]->(f), (d)-[r8:Road{time:1, dist:4}]->(c), (d)-[r9:Road{time:2, dist:12}]->(f), (e)-[r10:Road{time:5, dist:5}]->(g), (f)-[r11:Road{time:4, dist:2}]->(g) RETURN a,b,c,d,e,f,g,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11" -{{< / highlight >}} +``` ![Road network](../images/graph_query_city.png) @@ -55,13 +55,13 @@ Before v2.10, you were able to solve these queries: ### Find the shortest path (by number of roads) from A to G -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}),(g:City{name:'G'}) WITH shortestPath((a)-[*]->(g)) as p RETURN length(p), [n in nodes(p) | n.name] as pathNodes" 1) 1) "length(p)" 2) "pathNodes" 2) 1) 1) (integer) 3 2) "[A, D, F, G]" -{{< / highlight >}} +``` `shortestPath` returns one of the shortest paths. If there is more than one, only one is retrieved. @@ -71,7 +71,7 @@ With RedisInsight v2, you can visualize a path simply by returning it. ### Find all the shortest paths (by number of roads) from A to G -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}),(g:City{name:'G'}) WITH a,g MATCH p=allShortestPaths((a)-[*]->(g)) RETURN length(p), [n in nodes(p) | n.name] as pathNodes" 1) 1) "length(p)" 2) "pathNodes" @@ -83,13 +83,13 @@ GRAPH.QUERY g "MATCH (a:City{name:'A'}),(g:City{name:'G'}) WITH a,g MATCH p=allS 2) "[A, D, E, G]" 4) 1) (integer) 3 2) "[A, B, E, G]" -{{< / highlight >}} +``` All `allShortestPaths` results have, by definition, the same length (number of roads). ### Find 5 shortest paths (by number of roads) from A to G -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH p = (a:City{name:'A'})-[*]->(g:City{name:'G'}) RETURN length(p), [n in nodes(p) | n.name] as pathNodes ORDER BY length(p) LIMIT 5" 1) 1) "length(p)" 2) "pathNodes" @@ -103,7 +103,7 @@ GRAPH.QUERY g "MATCH p = (a:City{name:'A'})-[*]->(g:City{name:'G'}) RETURN lengt 2) "[A, C, F, G]" 5) 1) (integer) 4 2) "[A, D, C, F, G]" -{{< / highlight >}} +``` Using the unbounded traversal pattern `(a:City{name:'A'})-[*]->(g:City{name:'G'})`, FalkorDB traverses all possible paths from A to G. `ORDER BY length(p) LIMIT 5` ensures that you collect only [up to 5 shortest paths (minimal number of relationships). This approach is very inefficient because all possible paths would have to be traversed. Ideally, you would want to abort some traversals as soon as you are sure they would not result in the discovery of shorter paths. @@ -111,7 +111,7 @@ Using the unbounded traversal pattern `(a:City{name:'A'})-[*]->(g:City{name:'G'} In a similarly inefficient manner, you can traverse all possible paths and collect the 5 shortest paths (in kilometers). -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH p = (a:City{name:'A'})-[*]->(g:City{name:'G'}) WITH p,reduce(dist=0, n IN relationships(p) | dist+n.dist) as dist return dist,[n IN nodes(p) | n.name] as pathNodes ORDER BY dist LIMIT 5" 1) 1) "dist" 2) "pathNodes" @@ -125,7 +125,7 @@ GRAPH.QUERY g "MATCH p = (a:City{name:'A'})-[*]->(g:City{name:'G'}) WITH p,reduc 2) "[A, D, F, G]" 5) 1) (integer) 16 2) "[A, C, F, G]" -{{< / highlight >}} +``` Again, instead of traversing all possible paths, you would want to abort some traversals as soon as you are sure that they would not result in the discovery of shorter paths. @@ -159,35 +159,35 @@ With `algo.SPaths`, you can solve queries like this. Set `weightProp` to `dist`: -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}),(g:City{name:'G'}) CALL algo.SPpaths( {sourceNode: a, targetNode: g, relTypes: ['Road'], weightProp: 'dist'} ) YIELD path, pathWeight RETURN pathWeight, [n in nodes(path) | n.name] as pathNodes" 1) 1) "pathWeight" 2) "pathNodes" 2) 1) 1) "12" 2) "[A, D, E, G]" -{{< / highlight >}} +``` ### Find the fastest path (in minutes) from A to G Continue as before, but now set `weightProp` to `time`. -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}),(g:City{name:'G'}) CALL algo.SPpaths( {sourceNode: a, targetNode: g, relTypes: ['Road'], weightProp: 'time'} ) YIELD path, pathWeight RETURN pathWeight, [n in nodes(path) | n.name] as pathNodes" 1) 1) "pathWeight" 2) "pathNodes" 2) 1) 1) "10" 2) "[A, D, F, G]" -{{< / highlight >}} +``` ### Find the shortest paths (in kilometers) from A to G -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}),(g:City{name:'G'}) CALL algo.SPpaths( {sourceNode: a, targetNode: g, relTypes: ['Road'], pathCount: 0, weightProp: 'dist'} ) YIELD path, pathWeight RETURN pathWeight, [n in nodes(path) | n.name] as pathNodes" 1) 1) "pathWeight" 2) "pathNodes" 2) 1) 1) "12" 2) "[A, D, E, G]" -{{< / highlight >}} +``` In the example above, you also specified the `pathCount` argument, where `pathCount` is the number of paths to report: @@ -199,7 +199,7 @@ In the example above, you also specified the `pathCount` argument, where `pathCo ### Find 5 shortest paths (in kilometers) from A to G -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}),(g:City{name:'G'}) CALL algo.SPpaths( {sourceNode: a, targetNode: g, relTypes: ['Road'], pathCount: 5, weightProp: 'dist'} ) YIELD path, pathWeight RETURN pathWeight, [n in nodes(path) | n.name] ORDER BY pathWeight" 1) 1) "pathWeight" 2) "[n in nodes(path) | n.name]" @@ -213,13 +213,13 @@ GRAPH.QUERY g "MATCH (a:City{name:'A'}),(g:City{name:'G'}) CALL algo.SPpaths( {s 2) "[A, C, F, G]" 5) 1) "16" 2) "[A, D, F, G]" -{{< / highlight >}} +``` ### Find 2 shortest paths (in kilometers) from A to G, where you can reach G in up to 12 minutes Another interesting feature is the introduction of path constraints ('bounded-cost'). Suppose that you want to find only paths where you can reach G in 12 minutes or less. -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}),(g:City{name:'G'}) CALL algo.SPpaths( {sourceNode: a, targetNode: g, relTypes: ['Road'], pathCount: 2, weightProp: 'dist', costProp: 'time', maxCost: 12} ) YIELD path, pathWeight, pathCost RETURN pathWeight, pathCost, [n in nodes(path) | n.name] ORDER BY pathWeight" 1) 1) "pathWeight" 2) "pathCost" @@ -229,7 +229,7 @@ GRAPH.QUERY g "MATCH (a:City{name:'A'}),(g:City{name:'G'}) CALL algo.SPpaths( {s 3) "[A, D, C, F, G]" 2) 1) "16" 2) "10" -{{< / highlight >}} +``` In the example above, you added the following optional arguments: @@ -248,7 +248,7 @@ You also yielded: Another interesting feature is the ability to revert or ignore the relationship direction. -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'D'}),(g:City{name:'G'}) CALL algo.SPpaths( {sourceNode: a, targetNode: g, relTypes: ['Road'], relDirection: 'both', pathCount: 1000, weightProp: 'dist'} ) YIELD path, pathWeight RETURN pathWeight, [n in nodes(path) | n.name] as pathNodes ORDER BY pathWeight" 1) 1) "pathWeight" 2) "pathNodes" @@ -272,7 +272,7 @@ GRAPH.QUERY g "MATCH (a:City{name:'D'}),(g:City{name:'G'}) CALL algo.SPpaths( {s 2) "[D, E, B, A, C, F, G]" 10) 1) "41" 2) "[D, F, C, A, B, E, G]" -{{< / highlight >}} +``` In the example above, you added the following optional argument: @@ -282,7 +282,7 @@ In the example above, you added the following optional argument: Suppose you want to repeat the query above but also limit the path-length (number of relationships along to path) to 4: -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'D'}),(g:City{name:'G'}) CALL algo.SPpaths( {sourceNode: a, targetNode: g, relTypes: ['Road'], relDirection: 'both', pathCount: 1000, weightProp: 'dist', maxLen: 4} ) YIELD path, pathWeight RETURN pathWeight, [n in nodes(path) | n.name] as pathNodes ORDER BY pathWeight" 1) 1) "pathWeight" 2) "pathNodes" @@ -298,7 +298,7 @@ GRAPH.QUERY g "MATCH (a:City{name:'D'}),(g:City{name:'G'}) CALL algo.SPpaths( {s 2) "[D, B, E, G]" 6) 1) "18" 2) "[D, A, C, F, G]" -{{< / highlight >}} +``` In the example above, you specified the following optional constraint: @@ -314,7 +314,7 @@ That's what the `algo.SSpaths` procedure (SS stands for _single source_) is all ### Find all paths from A if the trip is limited to 10 kilometers -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}) CALL algo.SSpaths( {sourceNode: a, relTypes: ['Road'], pathCount: 1000, costProp: 'dist', maxCost: 10} ) YIELD path, pathCost RETURN pathCost, [n in nodes(path) | n.name] as pathNodes ORDER BY pathCost" 1) 1) "pathCost" 2) "pathNodes" @@ -332,11 +332,11 @@ GRAPH.QUERY g "MATCH (a:City{name:'A'}) CALL algo.SSpaths( {sourceNode: a, relTy 2) "[A, C]" 7) 1) "10" 2) "[A, B, E]" -{{< / highlight >}} +``` ### Find all paths from A if the trip is limited to 8 minutes -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}) CALL algo.SSpaths( {sourceNode: a, relTypes: ['Road'], pathCount: 1000, costProp: 'time', maxCost: 8} ) YIELD path, pathCost RETURN pathCost, [n in nodes(path) | n.name] as pathNodes ORDER BY pathCost" 1) 1) "pathCost" 2) "pathNodes" @@ -356,11 +356,11 @@ GRAPH.QUERY g "MATCH (a:City{name:'A'}) CALL algo.SSpaths( {sourceNode: a, relTy 2) "[A, D, C, F]" 8) 1) "8" 2) "[A, D, E]" -{{< / highlight >}} +``` ### Find 5 shortest paths (in kilometers) from A -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}) CALL algo.SSpaths( {sourceNode: a, relTypes: ['Road'], pathCount: 5, weightProp: 'dist', costProp: 'cost'} ) YIELD path, pathWeight, pathCost RETURN pathWeight, pathCost, [n in nodes(path) | n.name] as pathNodes ORDER BY pathWeight" 1) 1) "pathWeight" 2) "pathCost" @@ -380,11 +380,11 @@ GRAPH.QUERY g "MATCH (a:City{name:'A'}) CALL algo.SSpaths( {sourceNode: a, relTy 5) 1) "8" 2) "1" 3) "[A, C]" -{{< / highlight >}} +``` ### Find 5 shortest paths (in kilometers) from A if the trip is limited to 6 minutes -{{< highlight bash >}} +```bash GRAPH.QUERY g "MATCH (a:City{name:'A'}) CALL algo.SSpaths( {sourceNode: a, relTypes: ['Road'], pathCount: 5, weightProp: 'dist', costProp: 'time', maxCost: 6} ) YIELD path, pathWeight, pathCost RETURN pathWeight, pathCost, [n in nodes(path) | n.name] as pathNodes ORDER BY pathWeight" 1) 1) "pathWeight" 2) "pathCost" @@ -404,4 +404,4 @@ GRAPH.QUERY g "MATCH (a:City{name:'A'}) CALL algo.SSpaths( {sourceNode: a, relTy 5) 1) "14" 2) "6" 3) "[A, D, F]" -{{< / highlight >}} \ No newline at end of file +``` \ No newline at end of file