{"id":15664385,"url":"https://github.com/jexp/cypher-rs","last_synced_at":"2025-05-06T19:10:28.305Z","repository":{"id":11114040,"uuid":"13471058","full_name":"jexp/cypher-rs","owner":"jexp","description":"Configurable Cypher REST endpoints","archived":false,"fork":false,"pushed_at":"2015-01-21T08:39:33.000Z","size":280,"stargazers_count":16,"open_issues_count":2,"forks_count":8,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-10-03T13:42:45.237Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","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/jexp.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}},"created_at":"2013-10-10T12:48:22.000Z","updated_at":"2021-02-25T12:34:54.000Z","dependencies_parsed_at":"2022-07-27T16:33:18.760Z","dependency_job_id":null,"html_url":"https://github.com/jexp/cypher-rs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jexp%2Fcypher-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jexp%2Fcypher-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jexp%2Fcypher-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jexp%2Fcypher-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jexp","download_url":"https://codeload.github.com/jexp/cypher-rs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221152506,"owners_count":16765055,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-10-03T13:42:21.940Z","updated_at":"2024-10-23T03:41:37.010Z","avatar_url":"https://github.com/jexp.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Cypher-RS\n\n*[Presentation about Cypher-RS](http://slideshare.net/neo4j/document-oriented-access-to-graphs)*\n\nNeo4j server-extension that allows to configure fixed REST-Endpoints for Cypher queries.\n\nYou can `PUT` cypher queries to an endpoint with a certain url-suffix and then later execute those queries by running\n\n* `GET` with query parameters, only readonly queries\n* `POST` with JSON (map, list of maps) payload for parameters\n* `POST` with CSV payload for parameters, with optional batch-size and delimiter\n\n### CREATE ENDPOINT\n\n    Verb: PUT\n    URL: /cypher-rs/\u003cyourEndpoint\u003e\n    Headers:\n        Content-type: plain/text\n    Body:\n        \u003cyourCypherRequest\u003e\n        \n#### Examples\n\n    PUT /cypher-rs/users\n    Content-type: plain/text\n    \n    Body:\n    MATCH (n:User) WHERE n.name={name} RETURN n\n    \n    --\u003e 201 Location: /cypher-rs/users\n\u003c/br\u003e\n\n    PUT /cypher-rs/create-user\n    Content-type: plain/text\n    \n    Body:\n    CREATE (n:Node {name:{name},age:{age},male:{male}})\n    \n    --\u003e 201 Location: /cypher-rs/create-user\n\n### QUERY ENDPOINT\n\n    Verb: GET\n    URL: /cypher-rs/\u003cyourEndpoint\u003e\n\n#### Examples\n\n    GET /cypher-rs/users?name=Andres\n\n    --\u003e 200\n    [\n        {\n            \"name\": \"Andres\",\n            \"age\": 21,\n            \"male\": true,\n            \"children\": [\n                \"Cypher\",\n                \"L.\",\n                \"N.\"\n            ]\n        }\n    ]\n\u003c/br\u003e\n\n    GET /cypher-rs/users?name=NotExists\n\n    --\u003e 204\n\n### POST JSON-DATA TO ENDPOINT\n\n    Verb: POST\n    URL: /cypher-rs/\u003cyourEndpoint\u003e\n    Headers:\n        Content-type: application/json\n    Body:\n        \u003cjsonData\u003e\n\n#### Examples\n\n    POST /cypher-rs/users \n    Content-type: application/json\n    \n    Body:\n    {\n        \"name\": \"Andres\"\n    }\n    \n    --\u003e 200\n    [\n        {\n            \"name\": \"Andres\",\n            \"age\": 21,\n            \"male\": true,\n            \"children\": [\n                \"Cypher\",\n                \"L.\",\n                \"N.\"\n            ]\n        }\n    ]\n\u003c/br\u003e\n\n    POST /cypher-rs/users \n    Content-type: application/json\n    \n    Body: \n    {\n        \"name\": \"NotExists\"\n    }\n    \n    --\u003e 204\n\u003c/br\u003e\n\n    POST /cypher-rs/users\n    Content-type: application/json\n    \n    Body:\n    [\n        {\n            \"name\": \"Andres\"\n        },\n        {\n            \"name\": \"Peter\"\n        },\n        {\n            \"name\": \"NotExists\"\n        }\n    ]\n    \n    --\u003e 200\n    [\n        {\n            \"name\": \"Andres\",\n            \"age\": 21,\n            \"male\": true,\n            \"children\": [\n                \"Cypher\",\n                \"L.\",\n                \"N.\"\n            ]\n        },\n        {\n            \"name\": \"Peter\",\n            \"age\": 32,\n            \"male\": true,\n            \"children\": [\n                \"Neo4j\",\n                \"O.\",\n                \"K.\"\n            ]\n        },\n        null\n    ]\n\n\n### POST CSV DATA TO ENDPOINT\n\n    Verb: POST\n    URL: /cypher-rs/\u003cyourEndpoint\u003e\n    Headers:\n        Content-type: text/plain\n    Body:\n        \u003ccsvData\u003e\n\n#### Examples\n\n    POST /cypher-rs/create-user\n    Content-type: text/plain\n    \n    Body:\n    name,age,male\\nAndres,21,true\n    \n    --\u003e 200\n    {\n        \"nodes_created\": 1,\n        \"labels_added\": 1,\n        \"properties_set\": 3,\n        \"rows\": 1\n    }\n\u003c/br\u003e\n\n    POST /cypher-rs/create-user?delim=\\t\u0026batch=20000\n    Content-type: text/plain\n    \n    Body: name\\tage\\tmale\\nAndres\\t21\\ttrue\n    \n    --\u003e 200\n    {\n        \"nodes_created\": 1,\n        \"labels_added\": 1,\n        \"properties_set\": 3,\n        \"rows\": 1\n    }\n\n### DELETE ENDPOINT\n\n    Verb: DELETE\n    URL: /cypher-rs/\u003cyourEndpoint\u003e\n\n#### Example\n\n    DELETE /cypher-rs/users\n\n    --\u003e 200 \n\n### LIST ENDPOINTS\n\n    Verb: GET\n    URL: /cypher-rs\n\n#### Example\n\n    GET /cypher-rs\n\n    --\u003e 200 [\"users\",\"create-user\"]\n\n    GET /cypher-rs?full=true\n\n    --\u003e 200 {\"users\": \"start n=node:node_auto_index(name={name}) return n\",\n             \"create-user\": \"create (n {name:{name},age:{age},male:{male}})\"}\n\n### GET ENDPOINT QUERY\n\n    Verb: GET\n    URL: /cypher-rs/\u003cyourEndpoint\u003e/query\n\n#### Example\n\n    GET /cypher-rs/users/query\n\n    --\u003e 200 start n=node:node_auto_index(name={name}) return n\n\n    GET /cypher-rs/create-users/query\n\n    --\u003e 200 create (n {name:{name},age:{age},male:{male}})\n\n### Types of results:\n\nsingle column, single row\n\n    [\n        {\n            \"name\": \"Andres\",\n            \"age\": 21,\n            \"male\": true,\n            \"children\": [\n                \"Cypher\",\n                \"L.\",\n                \"N.\"\n            ]\n        }\n    ]\n\nsingle column, multiple rows\n\n    [\n        {\n            \"name\": \"Andres\",\n            \"age\": 21,\n            \"male\": true,\n            \"children\": [\n                \"Cypher\",\n                \"L.\",\n                \"N.\"\n            ]\n        },\n        {\n            \"name\": \"Peter\",\n            \"age\": 32,\n            \"male\": true,\n            \"children\": [\n                \"Neo4j\",\n                \"O.\",\n                \"K.\"\n            ]\n        }\n    ]\n\nmultiple columns, single row (column names are keys)\n\n    [\n        {\n            \"user\": \"Andres\",\n            \"friends\": [\n                \"Peter\",\n                \"Michael\"\n            ]\n        }\n    ]\n\nmultiple columns, multiple rows (column names are keys)\n\n    [\n        {\n            \"user\": \"Andres\",\n            \"friends\": [\n                \"Peter\",\n                \"Michael\"\n            ]\n        },\n        {\n            \"user\": \"Michael\",\n            \"friends\": [\n                \"Peter\",\n                \"Andres\"\n            ]\n        },\n        {\n            \"user\": \"Peter\",\n            \"friends\": [\n                \"Andres\",\n                \"Michael\"\n            ]\n        }\n    ]\n\n### Configuration\n\nBuild with `mvn clean install dependency:copy-dependencies`\n\nCopy files `cp target/cypher-rs-2.1-SNAPSHOT.jar target/dependency/opencsv-2.3.jar path/to/server/plugins`\n\nAdd this line to `path/to/server/conf/neo4j-server.properties`\n\n    org.neo4j.server.thirdparty_jaxrs_classes=org.neo4j.cypher_rs=/cypher-rs\n\n\n### Notes\n\nThere is some magic happening with converting query parameters to cypher parameters, as query-parameters are all strings\nthings that look like a number are converted to numbers and collections (aka multiple query parameters) are converted into\nlists.\n\n\n### Ideas\n\n* all endpoints should be able to generate CSV when supplied with the accept header\n* replace Jackson with faster Gson?\n* performance tests\n\n### Concrete Example for the Movie-Graph in Neo4j-Server\n\n#### A \"movie and cast\" endpoint\n\n* parameter: `title`\n* result: a document with the movie title and a collection of cast names\n\n````bash\ncurl -i -XPUT -H content-type:text/plain \\\n -d'MATCH (movie:Movie {title:{title}})\n    OPTIONAL MATCH (movie)\u003c-[:ACTED_IN]-(actor)\n    RETURN {title:movie.title, cast: collect(actor.name)} as movie' \\\n http://localhost:7474/cypher-rs/movie\n\n// use it\n\ncurl http://localhost:7474/cypher-rs/movie?title=The%20Matrix\n````\n\n#### A \"co-actors\" endpoint\n\n* parameter: `name`\n* result: a document of the requested actor and actors who co-acted in the same movies, ordered by frequency\n\n````bash\ncurl -i -XPUT -H content-type:text/plain \\\n -d'MATCH (actor:Person {name:{name}})-[:ACTED_IN*2..2]-(co_actor)\n    WITH actor.name as name, {name:co_actor.name, count: count(*)} as co_actors\n    ORDER BY count(*) DESC\n    RETURN {name:name, co_actors: collect(co_actors)} as result' \\\n http://localhost:7474/cypher-rs/co-actor\n\n// use it\n\ncurl -i http://localhost:7474/cypher-rs/co-actor?name=Keanu%20Reeves\n````\n\n#### A \"create movie only\" endpoint\n\n* parameters: `title` and `released`\n* result: document with the movie's properties\n* uses `MERGE` as \"get-or-create\" operation\n\n````bash\ncurl -i -XPUT -H content-type:text/plain \\\n-d'MERGE (movie:Movie {title:{title}}) ON CREATE SET movie.released={released} RETURN movie' \\\n http://localhost:7474/cypher-rs/create-movie\n\n// use it\n\ncurl -i -XPOST -H content-type:application/json -d'{\"title\":\"Forrest Gump\",\"released\":1994}' http://localhost:7474/cypher-rs/create-movie\n````\n\n#### A \"create movie with cast\" endpoint\n\n* parameters: `title`, `released` for the movies, `actors` for the actor names\n* result: document with the movie's properties\n* uses `MERGE` as \"get-or-create\" operation for both movie and actors\n\n````bash\ncurl -i -XPUT -H content-type:text/plain \\\n-d'MERGE (movie:Movie {title:{title}}) ON CREATE SET movie.released={released}\n   FOREACH (name in {actors} | MERGE (actor:Person {name:name}) MERGE (actor)-[:ACTED_IN]-\u003e(movie))\n   RETURN movie' \\\n http://localhost:7474/cypher-rs/create-movie2\n\n// use it\n\ncurl -i -XPOST -H content-type:application/json -d'{\"title\":\"Forrest Gump\",\"released\":1994, \"actors\":[\"Tom Hanks\",\"Robin Wright\",\"Gary Sinise\"]}' http://localhost:7474/cypher-rs/create-movie2\n\ncurl http://localhost:7474/cypher-rs/movie?title=Forrest%20Gump\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjexp%2Fcypher-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjexp%2Fcypher-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjexp%2Fcypher-rs/lists"}