<> Nebula seems like a decent fit, but getting started with it is a bit tricky, and there's a lot of outdated docs floating around. While it has a proper large-scale architecture, I want to just use it on my workstation for now, so I'll use the docker-compose method. = Start the database = I don't think this has persistence, so expect to redo all your work if you the workstation is shutdown. I don't know for sure, because I've never used docker-compose before. These docs are old but they work fine to get it up and running: https://docs.nebula-graph.io/2.0/2.quick-start/2.deploy-nebula-graph-with-docker-compose/ * Note that the default port has changed from 3699, and it's now 9669 * If you need to do some debugging with docker: https://medium.com/nebula-graph/debug-the-nebula-graph-processes-inside-the-docker-container-3e28dc5fafe8 = Connect to the console = {{{ docker run --rm -it --network nebula-docker-compose_nebula-net --entrypoint=/bin/sh vesoft/nebula-console:v2-nightly / # nebula-console -addr graphd -port 9669 -u root -p nebula }}} This is like a mysql/psql shell now. `:QUIT` to exit. = Make some structure = I'm using this series of videos: https://www.youtube.com/watch?v=qF4ZhDEN30k&list=PL4ArMmsAnb84uB2d9L46eXpIi7Epz2cfp&index=3 The syntax has changed a little since then though, here's the reference: https://docs.nebula-graph.io/3.2.0/3.ngql-guide/9.space-statements/1.create-space/ {{{ (root@nebula) [(none)]> CREATE SPACE mneme (vid_type = int64); Execution succeeded (time spent 1229/1435 us) (root@nebula) [(none)]> USE mneme; (root@nebula) [mneme]> CREATE TAG person (displayname string NOT NULL, dob_year INT, dob_month INT, dob_day INT) comment = 'A single identifiable person, who may have multiple handles/names'; (root@nebula) [mneme]> CREATE TAG handle (name STRING NOT NULL, context STRING, url STRING) comment = 'A name that a Person is known by, in a specific context or situation'; (root@nebula) [mneme]> CREATE TAG photoshoot(shoot_date DATE NOT NULL, shoot_name STRING); (root@nebula) [mneme]> CREATE EDGE did_shoot(role STRING); (root@nebula) [mneme]> CREATE TAG location(name STRING, coords GEOGRAPHY) comment = 'Usually a LatLong of a point, but could be a linestring or polygon'; (root@nebula) [mneme]> CREATE EDGE shot_at(); (root@nebula) [mneme]> CREATE EDGE known_as(); }}} = Create some data = {{{ INSERT VERTEX person(displayname, dob_year, dob_month, dob_day) VALUES 1:("Barney Desmond", 1989, 12, 13); INSERT VERTEX handle(name) VALUES 2:("furinkan"); INSERT EDGE known_as() VALUES 1 -> 2:(); INSERT VERTEX person(displayname) VALUES 3:("Victoria Ho"); INSERT VERTEX handle(name) VALUES 4:("dboomer"); INSERT EDGE known_as() VALUES 3 -> 4:(); INSERT VERTEX person(displayname) VALUES 5:("Jessica Li"); INSERT VERTEX handle(name, context, url) VALUES 6:("Kisara Shimada", "Facebook", "https://www.facebook.com/kisarawastaken"); INSERT VERTEX handle(name, context, url) VALUES 7:("aerithxzack", "Instagram", "https://www.instagram.com/aerithxzack/"); INSERT VERTEX handle(name, context, url) VALUES 8:("Kisa_9225", "Twitter", "https://twitter.com/Kisa_9225"); // these could be a single INSERT, that's fine too INSERT EDGE known_as() VALUES 5 -> 6:() ; INSERT EDGE known_as() VALUES 5 -> 7:() ; INSERT EDGE known_as() VALUES 5 -> 8:() ; }}} = Now with some masking = {{{ INSERT VERTEX handle(name) VALUES 9:("Valerious"); INSERT VERTEX location(name, coords) VALUES 10:("International Convention Centre Sydney", ST_GeogFromText("POINT(151.199 -33.8734)")); INSERT VERTEX photoshoot(shoot_date, shoot_name) VALUES 11:(date("2020-03-08"), "Madman Anime Festival"); INSERT VERTEX handle(name) VALUES 12:("shortgirls.net"); INSERT EDGE known_as() VALUES 1 -> 12:(); INSERT EDGE shot_at() VALUES 11 -> 10:() ; INSERT EDGE did_shoot(role) VALUES 9 -> 11:("cosplayer") ; INSERT EDGE did_shoot(role) VALUES 12 -> 11:("photographer") ; }}} Valerious is a cosplayer, but she doesn't have a Person associated with her. As demonstrated here: {{{ (root@nebula) [mneme]> GO FROM 11 OVER did_shoot REVERSELY YIELD properties($$).name AS participant; +------------------+ | participant | +------------------+ | "Valerious" | | "shortgirls.net" | +------------------+ // Now try and map that back to a real person > GO FROM 11 OVER did_shoot REVERSELY YIELD did_shoot._dst as hid | \ GO FROM $-.hid OVER known_as REVERSELY YIELD $^.handle.name AS handle, properties($$).displayname AS person_name; +------------------+------------------+ | handle | person_name | +------------------+------------------+ | "shortgirls.net" | "Barney Desmond" | +------------------+------------------+ }}} = Inspect it with the studio = The Studio is basically a nice web-enabled console. {{{ docker pull vesoft/nebula-graph-studio:v3.4.0 docker run -d -it -p 7001:7001 vesoft/nebula-graph-studio:v3.4.0 }}} Hit it on http://localhost:7001/ You can connect with: * 192.168.1.12:9669 * root * nebula