{"id":21532773,"url":"https://github.com/sfproductlabs/jelass","last_synced_at":"2026-03-09T10:02:03.915Z","repository":{"id":142073834,"uuid":"228509806","full_name":"sfproductlabs/jelass","owner":"sfproductlabs","description":"Janus + Elastic Search + Cassandra docker container with SSL Client Certificates implemented.","archived":false,"fork":false,"pushed_at":"2020-11-04T21:09:55.000Z","size":2337,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-10T00:41:43.212Z","etag":null,"topics":["bigtable","cassandra","cassandra-cql","cassandra-database","cassandra-elastic-search","cstar-compiler","datastax","elassandra","elassandra-cluster","elassandra-example","elastic-data","elasticsearch","gremlin","janus","janusgraph","scylla","scylladb","strapdata","tinkerpop"],"latest_commit_sha":null,"homepage":"","language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sfproductlabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-17T01:47:01.000Z","updated_at":"2023-09-24T17:10:33.000Z","dependencies_parsed_at":"2023-09-03T05:31:14.299Z","dependency_job_id":null,"html_url":"https://github.com/sfproductlabs/jelass","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sfproductlabs/jelass","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfproductlabs%2Fjelass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfproductlabs%2Fjelass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfproductlabs%2Fjelass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfproductlabs%2Fjelass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sfproductlabs","download_url":"https://codeload.github.com/sfproductlabs/jelass/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfproductlabs%2Fjelass/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30290921,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bigtable","cassandra","cassandra-cql","cassandra-database","cassandra-elastic-search","cstar-compiler","datastax","elassandra","elassandra-cluster","elassandra-example","elastic-data","elasticsearch","gremlin","janus","janusgraph","scylla","scylladb","strapdata","tinkerpop"],"created_at":"2024-11-24T02:22:04.138Z","updated_at":"2026-03-09T10:02:03.910Z","avatar_url":"https://github.com/sfproductlabs.png","language":"Dockerfile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Jelass (jĕl′əs), a Linearly Scalable, Searchable, NoSQL and Graph Database\n\nWith a database like this, all your friends will be jealous.\n\n## Jelass = JanusGraph + Elassandra (Elastic Search + Cassandra) \n\nElassandra stores Elastic data on Cassandra. So there's no double up on this system. Cassandra is the boss. Elastic runs on top of it and allows it to be useful (searchable, querying etc.). Janus comes to town and adds all the graph functionality LinkedIn could ever need. All under the one roof.\n\nHow is this different from straight Janus? Janus' elastic data isn't stored in Cassandra. This has all 3 together. Bullet-proof. \n\n## Download Docker Image\n\nhttps://hub.docker.com/repository/docker/sfproductlabs/jelass\n\n### Running in docker-compose \n\nSee example https://github.com/sfproductlabs/tracker/blob/master/docker-compose.yml\n\nEnsure you have enough memory.\n\n## Connecting\n- `cqlsh --ssl`\n- Remotely: `./bin/gremlin.sh` then `:remote connect tinkerpop.server conf/remote.yaml`\n- Or locally: `./bin/gremlin.sh` then `graph = JanusGraphFactory.open('conf/gremlin-server/janusgraph-cql-es-server.properties')` \n- etc.\n\n## Starting out\n\n### Starting with JanusGraph\n\nThen try the basic demo:\n\nOn the console hosting docker run:\n```bash\ndocker ps\n#then replace [container_number] with your docker container hash\ndocker exec -it [container_number] bash\n```\nThen inside the docker container:\n```bash\ncd /app/ela/janusgraph-full-0.5.2\n./bin/gremlin.sh\n```\n\nThen inside the `gremlin\u003e` console (**also works remotely**) you may need to change the ip:\n\n```\ncluster = Cluster.open('conf/remote-objects.yaml')\ngraph = EmptyGraph.instance()\ng = graph.traversal().withRemote(DriverRemoteConnection.using(cluster, \"g\"))\n// graph = EmptyGraph.instance()\n// g = graph.traversal().withRemote('conf/remote-graph.properties')\n// TinkerPop Predicates\ng.V().has('age',within(5000))\ng.V().has('age',without(5000))\ng.V().has('age',within(5000,45))\ng.V().has('age',inside(45,5000)).valueMap(true)\ng.V().and(has('age',between(45,5000)),has('name',within('pluto'))).valueMap(true)\ng.V().or(has('age',between(45,5000)),has('name',within('pluto','neptune'))).valueMap(true)\n\n// Janus Graph Geo Predicates\ng.E().has('place', geoIntersect(Geoshape.circle(37.97, 23.72, 50)))\ng.E().has('place', geoWithin(Geoshape.circle(37.97, 23.72, 50)))\ng.E().has('place', geoDisjoint(Geoshape.circle(37.97, 23.72, 50)))\n\n// master branch only\ng.addV().property('place', Geoshape.circle(37.97, 23.72, 50))\ng.V().has('place', geoContains(Geoshape.point(37.97, 23.72)))\n\n// Janus Graph Text Predicates\ng.V().has('name',textContains('neptune')).valueMap(true)\ng.V().has('name',textContainsPrefix('nep')).valueMap(true)\ng.V().has('name',textContainsRegex('nep.*')).valueMap(true)\ng.V().has('name',textPrefix('n')).valueMap(true)\ng.V().has('name',textRegex('.*n.*')).valueMap(true)\n\n// master branch only\ng.V().has('name',textContainsFuzzy('neptun')).valueMap(true)\ng.V().has('name',textFuzzy('nepitne')).valueMap(true)\n```\nYou can also run the examples locally:\n\n```gremlin\ngraph = JanusGraphFactory.open('conf/gremlin-server/janusgraph-cql-es-server.properties')\nGraphOfTheGodsFactory.load(graph)\ng = graph.traversal()\nsaturn = g.V().has('name', 'saturn').next()\ng.V(saturn).valueMap()\ng.V(saturn).in('father').in('father').values('name')\n\n//Add a fulltext index on a new property alias\nmgmt = graph.openManagement()\nsummary = mgmt.makePropertyKey('alias').dataType(String.class).make()\nmgmt.buildIndex('alias', Vertex.class).addKey(summary, Mapping.TEXTSTRING.asParameter()).buildMixedIndex(\"search\")\nmgmt.commit()\ng.addV('person').property('alias','bob')\ng.V().has('alias', textContains('bob')).hasNext()\ngraph.tx().commit()\n```\n### Dropping a graph\n\n./bin/gremlin.sh\n```\ngraph = JanusGraphFactory.open('conf/gremlin-server/janusgraph-cql-es-server.properties')\ng = graph.traversal()\ng.V().drop().iterate()\n```\nor\n\n\n```JanusGraphFactory.drop(graph);```\n\n### Checking Schema\n\n```\nmgmt = graph.openManagement()\nmgmt.printSchema()\n```\n\n## Using Elassandra (Cassandra + Elastic Search)\n\nhttps://elassandra.readthedocs.io/\n\n### Post-install\n\nOn a production environment, we recommand to to modify some system settings such as disabling swap. This guide shows you how to do it. On linux, you should install jemalloc.\n\n#### Optimizing for Janusgraph Batch writes\n\nSetup batch loading for the service:\n```\necho \"storage.batch-loading=true\" \u003e\u003e ./conf/gremlin-server/janusgraph-cql-es-server.properties\necho \"schema.default=none\" \u003e\u003e ./conf/gremlin-server/janusgraph-cql-es-server.properties\n```\n\n## Visualization of Janus\n\n* [Graph Explorer](https://github.com/invanalabs/graph-explorer)\n\ndocker run -p 8889:8888 -d --name graph-explorer sfproductlabs/graph-explorer:latest\n\nOpen the Url: http://localhost:8889\n\nThen connect to: `ws://localhost:8182/gremlin` \n\nThe creator created a great little [CRUD intro](https://medium.com/invanalabs/crud-cheatsheet-to-apache-tinkerpop-gremlin-393540cd46ae).\n\nAfter you have created your first few nodes and edges try this in the query editor:\n```\nnodes=g.V().toList();edges=g.E().toList();[nodes,edges]\n```\n\n## Cassandra Tools\n\nhttps://cassandra.apache.org/third-party/\n\n### Backup \u0026 Restore\n\nBackup a _single instance_ (example uses keyspace `scrp` replace your keyspace name with this):\n```bash\ncqlsh --ssl -e \"desc scrp\" \u003e /tmp/scrp.cql\nnodetool snapshot scrp\ncd /var/lib/cassandra\ntar -czvf /tmp/scrp.tgz $(find . -type f | grep 1603309754293)\n```\n\nRestore the instance by copying into a directory:\n```bash\ncd /tmp/\ncqlsh --ssl -f /tmp/scrp.cql\ntar -xzvf /tmp/scrp.tgz\ncd /tmp/data/\nfind . -type f -execdir mv {} ../.. \\;\ncd scrp\nfor x in *;do sstableloader -v --conf-path /etc/cassandra/cassandra.yaml -d 172.19.0.3 /tmp/data/scrp/$x;done\n```\n\n#### Consolidating and Managing Backups across Datacenters\n\nI personally use a grandfather,father,son model for backups using a tool called Borg:\n\nhttps://www.borgbackup.org/demo.html\n\n## Diagnostics\n\n```bash\ncurl -XGET http://$CASSANDRA_HOST:9200/_cluster/state?pretty\nnodetool repair -full\nnodetool cleanup\nnodetool flush\n#nodetool rebuild_index sfpla events_recent events_recent_idx\nnodetool gossipinfo\nnodetool tpstats\nnodetool describecluster\nnodetool statusthrift\nnodetool statusgossip\nnodetool ring\nnodetool status\nnodetool status elastic_admin\nnodetool cfstats | grep read | grep latency\n#less /var/log/cassandra/system.log\n# ...\n#cqlsh --ssl\n#cqlsh\u003eselect * from elastic_admin.Metadata_log;\n```\n\n## Using Python\n\nhttps://docs.janusgraph.org/connecting/python/\n- [ ] TODO: Connecting to spark/superset\n\n\n## TODO\n\n- [ ] TODO: Visualization in Elassandra. Superset. Spark.\n\n## Running \u0026 Ready for Production\n- [x] Docker with SSL by default\n- [x] Nginx SSL for elastic search (Available on port 443 \u0026 port 9343, using nginx reverse proxy)\n- [x] Cassandra client and server keystores by default\n- [ ] TODO: add nginx streaming SSL for tinkerpop on 8182\n\n### Make sure to update the replication factor of  \"elastic_admin\"\nEx. ```alter keyspace elastic_admin WITH replication = {'class': 'NetworkTopologyStrategy', 'DC1' : 2};```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsfproductlabs%2Fjelass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsfproductlabs%2Fjelass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsfproductlabs%2Fjelass/lists"}