Showme
Dynamic APIs are integral to how users interact with data. GraphGrid Showmes allow developers to create their own APIs using only Geequel. In this tutorial you will learn the basics of Showmes using ONgDB's movie dataset. We recommend completing the Movie Database tutorial before moving on to this one. The Movie Database tutorial teaches you how to make your own graph using ONgDB's movie dataset, and how to visualize it in the Dashboard. We'll be using those basics in this tutorial.
Showme Module Tutorial Overview
/getMoviesByYear
Showme- Create a Showme called
getMoviesByYear
. - Execute the
/getMoviesByYear
Showme.
- Create a Showme called
/shortestPath
Showme- Create a Showme called
shortestPath
- Execute the
shortestPath
Showme.
- Create a Showme called
- Add a Showme to the Dashboard.
Create a Showme
/getMoviesByYear
Let's make a Showme that will create an endpoint that will allow a user to return a list of movies released in a certain year. Now that we have defined what we want our endpoint to do, we need to answer the following questions:
What query will need to be run to access the data that we need?
We know that we'll need to query nodes with a
Movie
label that match the value of the parameterreleased
. We can pass in this Geequel into our request:
MATCH (m:Movie {released:$released}) RETURN m
What is the method of this request?
Since we are retrieving information from the database the method for this endpoint will be a
GET
request.
What do we want to name our path?
/getMoviesByYear
sounds good!
What parameters will we need to include and/or require in this request?
In order for this request to be successful we need to include in our params
released
as a key.
The entire /createShowMe
request including the body we created will look like this:
You can use either the /createShowMe
and /updateShowMe
to create a Showme. Just note that for /updateShowMe
has slightly different parameters.
Instead of nodeTypeGrns
and params
/updateShowMe
uses addNodeTypeGrns
and addParams
.
curl --location --request POST "${API_BASE}/1.0/showme/createShowMe" \
--header "Authorization: Bearer ${BEARER_TOKEN}" \
--header 'Content-Type: application/json' \
--data-raw '
{
"cypher": "MATCH (m:Movie {released:$released}) RETURN m",
"showMeMethod": "GET",
"showMePath": "/getMoviesByYear",
"showMeDisplayValue": "getMoviesByYear",
"showMeDefinition": "Returns a list of movies released in a specific year",
"showMePopulatorDisplayValue": "getMoviesByYear",
"showMePopulatorDefinition": "getMoviesByYear",
"nodeTypeGrns": [],
"params": {
"released": ""
},
"requiredParams": [],
"cypherOrder": 0,
"overrideCypherOrder": false
}'
And the response will look like this:
{
"showMe": {
"id": 66,
"labels": [],
"enver": 0,
"createdAt": "2021-04-27T16:43:33.164Z",
"updatedAt": "2021-04-27T16:43:33.164Z",
"createdBy": "graphgrid",
"lastModifiedBy": "graphgrid",
"grn": "grn:gg:graphgridshowme:HrT9QxjdnnVoV0owQODCnD00zrPHuyul4cTjmXypWWp1",
"key": "GET /getMoviesByYear",
"method": "GET",
"path": "/getMoviesByYear",
"definition": "Returns a list of movies released in a specific year",
"displayValue": "getMoviesByYear",
"order": null,
"disableUserRoleRequirement": null,
"nodeTypes": [],
"showMePopulator": {
"id": 65,
"labels": [],
"enver": 0,
"createdAt": "2021-04-27T16:43:33.152Z",
"updatedAt": "2021-04-27T16:43:33.179Z",
"createdBy": "graphgrid",
"lastModifiedBy": "graphgrid",
"grn":"grn:gg:graphgridshowmepopulator:3Bb7MPFpJ5xtHh6nsYL2YMjVAJQsRfwxjSIz820WWRKI",
"cypher": "MATCH (m:Movie {released:$released}) RETURN m",
"displayValue": "getMoviesByYear",
"definition": "getMoviesByYear",
"requiredParameters": [],
"searchQuery": null,
"successRoutes": [],
"failureRoutes": [],
"conditionalSuccessRoutes": [],
"conditionalFailureRoutes": [],
"parameters": [
{
"id": 305,
"labels": [],
"enver": 0,
"createdAt": "2021-04-27T16:43:33.154Z",
"updatedAt": "2021-04-27T16:43:33.154Z",
"createdBy": "graphgrid",
"lastModifiedBy": "graphgrid",
"grn": "grn:gg:graphgridshowmeparameter:sizHGDyypOprw1pkn3UccpdqAzhJyzjM07NyGY5wMIAA",
"type": "java.util.LinkedHashMap",
"key": "released",
"value": "{}",
"encryption": null,
"grnType": "graphgridshowmeparameter",
"label": "GraphGridShowMeParameter"
}
],
"snippets": [],
"snippetImpls": null,
"cypherOrder": 0,
"grnType": "graphgridshowmepopulator",
"label": "GraphGridShowMePopulator"
},
"securityRules": null,
"grnType": "graphgridshowme",
"label": "GraphGridShowMe"
},
"showMePopulator": {
"id": 65,
"labels": [],
"enver": 0,
"createdAt": "2021-04-27T16:43:33.152Z",
"updatedAt": "2021-04-27T16:43:33.179Z",
"createdBy": "graphgrid",
"lastModifiedBy": "graphgrid",
"grn": "grn:gg:graphgridshowmepopulator:3Bb7MPFpJ5xtHh6nsYL2YMjVAJQsRfwxjSIz820WWRKI",
"cypher": "MATCH (m:Movie {released:$released}) RETURN m",
"displayValue": "getMoviesByYear",
"definition": "getMoviesByYear",
"requiredParameters": [],
"searchQuery": null,
"successRoutes": [],
"failureRoutes": [],
"conditionalSuccessRoutes": [],
"conditionalFailureRoutes": [],
"parameters": [
{
"id": 305,
"labels": [],
"enver": 0,
"createdAt": "2021-04-27T16:43:33.154Z",
"updatedAt": "2021-04-27T16:43:33.154Z",
"createdBy": "graphgrid",
"lastModifiedBy": "graphgrid",
"grn": "grn:gg:graphgridshowmeparameter:sizHGDyypOprw1pkn3UccpdqAzhJyzjM07NyGY5wMIAA",
"type": "java.util.LinkedHashMap",
"key": "released",
"value": "{}",
"encryption": null,
"grnType": "graphgridshowmeparameter",
"label": "GraphGridShowMeParameter"
}
],
"snippets": [],
"snippetImpls": null,
"cypherOrder": 0,
"grnType": "graphgridshowmepopulator",
"label": "GraphGridShowMePopulator"
}
}
/executeShowMe/getMoviesByYear
Now we can see our newly created endpoint in action by executing the Showme.
Run this request passing in the path of our Showme /getMoviesByYear
and our params {"released":1999}
. This /executeShowMe
request
should return the results for the key "released" that has a value of 1999.
Parameters must be URL encoded for GET
requests.
curl --location --request GET "${API_BASE}/1.0/showme/executeShowMe/getMoviesByYear?params=%7B%22released%22%3A1999%7D" \
--header "Authorization: Bearer ${BEARER_TOKEN}"
Our response shows a list of movies that were released in 1999:
{
"results": [
{
"m": {
"labels": [
"Resource",
"Movie",
"GraphGridResource"
],
"id": 18,
"properties": {
"createdAt": "2021-04-26T20:19:55+00:00",
"grn": "grn:gg:movie:HCzJLaDkzJL3EvkGHMBIwDHxmb6xKPSshu9DLihqNuaI",
"lastSearchIndexedAt": "0",
"tagline": "One robot's 200 year journey to become an ordinary man.",
"title": "Bicentennial Man",
"released": 1999,
"updatedAt": "2021-04-26T20:19:55+00:00"
}
}
},
{
"m": {
"labels": [
"Resource",
"Movie",
"GraphGridResource"
],
"id": 46,
"properties": {
"createdAt": "2021-04-26T20:19:55+00:00",
"grn": "grn:gg:movie:ryRIh16x7oMFrkf9IX9Xx70HLyR8unhm8cXOvEDbZIBY",
"lastSearchIndexedAt": "0",
"tagline": "Walk a mile you'll never forget.",
"title": "The Green Mile",
"released": 1999,
"updatedAt": "2021-04-26T20:19:55+00:00"
}
}
},
{
"m": {
"labels": [
"Resource",
"Movie",
"GraphGridResource"
],
"id": 103,
"properties": {
"createdAt": "2021-04-26T20:19:55+00:00",
"grn": "grn:gg:movie:pHwiHrVucvcsifSO2A58X6QiCYdvkiA4SSaFSdCXFD1d",
"lastSearchIndexedAt": "0",
"tagline": "Welcome to the Real World",
"title": "The Matrix",
"released": 1999,
"updatedAt": "2021-04-26T20:19:55+00:00"
}
}
},
{
"m": {
"labels": [
"Resource",
"Movie",
"GraphGridResource"
],
"id": 165,
"properties": {
"createdAt": "2021-04-26T20:19:55+00:00",
"grn": "grn:gg:movie:0mTK8k4FJ6Nrl9sPNVVTbdHIqPQgyOynYUX9Tr727VH7",
"lastSearchIndexedAt": "0",
"tagline": "First loves last. Forever.",
"title": "Snow Falling on Cedars",
"released": 1999,
"updatedAt": "2021-04-26T20:19:55+00:00"
}
}
}
],
"bookmark": "neo4j:bookmark:v1:tx2175",
"errors": []
}
/shortestPath
This Showme example is a bit more advanced, but presents just how much Showmes can be customized to handle your data to get interesting
insights! The /shortestPath
Showme will take in two parameters of two person nodes. The Showme will return the shortest path through
edgeType relationships between them.
The Geequel query we need to run to get the shortest path between two nodes will looks like this:
MATCH (p1:Person) WHERE p1.grn = {firstPersonGrn} MATCH (p2:Person) WHERE p2.grn = {secondPersonGrn} MATCH p=allShortestPaths((p1)-[*]-(p2)) WHERE NONE(n IN nodes(p) WHERE n:Version) WITH nodes(p) AS shortestPathNodes UNWIND shortestPathNodes AS shortestPathNode RETURN COLLECT(shortestPathNode.grn) AS nodeIds
This query sets two parameters: firstPersonGrn
and secondPersonGrn
and uses all edgeTypes to find the shortest path between them.
Here's the full create Showme request:
curl --location --request PUT "${API_BASE}/1.0/showme/updateShowMe/shortestPath" \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${BEARER_TOKEN}" \
--data-raw '{
"cypher": "MATCH (p1:Person) WHERE p1.grn = {firstPersonGrn} MATCH (p2:Person) WHERE p2.grn = {secondPersonGrn} MATCH p=allShortestPaths((p1)-[*]-(p2)) WHERE NONE(n IN nodes(p) WHERE n:Version) WITH nodes(p) AS shortestPathNodes UNWIND shortestPathNodes AS shortestPathNode RETURN COLLECT(shortestPathNode.grn) AS nodeIds",
"showMeMethod": "GET",
"showMePath": "/shortestPath",
"showMeDisplayValue": "shortestPath",
"showMeDefinition": "shortest path between two people",
"showMePopulatorDisplayValue": "shortestPath",
"showMePopulatorDefinition": "shortestPath",
"addNodeTypeGrns": [],
"addParams": {
"firstPersonGrn": "",
"secondPersonGrn": ""
},
"requiredParams": ["firstPersonGrn","secondPersonGrn"],
"cypherOrder": 0,
"overrideCypherOrder": false
}
'
/executeShowMe/shortestPath
Let's see our Showme in action! Run the /executeShowMe request with URL encoded params for firstPersonGrn
and secondPersonGrn
. This
request queries the shortest path between Keanu Reeves and Al Pacino.
curl --location --request GET "${API_BASE}/1.0/showme/executeShowMe/shortestPath?params=%7B%22firstPersonGrn%22%3A%22grn%3Agg%3Aperson%3AVd0D6CdJ4T3RmkYhyCAneDFEX5WJWU9H1P450TsPXhT9%22%2C%20%22secondPersonGrn%22%3A%22grn%3Agg%3Aperson%3ApKMmKbKTseEGadwaM3EYOBrvKlTJpr5ICctdnfNYv4DP%22%7D" \
--header "Authorization: Bearer ${BEARER_TOKEN}"
Response:
{
"results": [{
"shortestPathNodes": [{
"labels": [
"Resource",
"Person",
"GraphGridResource"
],
"id": 355,
"properties": {
"createdAt": "2021-04-28T21:52:29+00:00",
"grn":"grn:gg:person:Vd0D6CdJ4T3RmkYhyCAneDFEX5WJWU9H1P450TsPXhT9",
"lastSearchIndexedAt": "0",
"born": 1940,
"name": "Al Pacino",
"updatedAt": "2021-04-28T21:52:29+00:00"
}
},
{
"labels": [
"Resource",
"Movie",
"GraphGridResource"
],
"id": 353,
"properties": {
"createdAt": "2021-04-28T21:52:29+00:00",
"grn": "grn:gg:movie:pO3MA539rBvsA4LXU26G0tFHm1vUDfznq1P3gksl6YeI",
"lastSearchIndexedAt": "0",
"tagline": "Evil has its winning ways",
"title": "The Devil's Advocate",
"released": 1997,
"updatedAt": "2021-04-28T21:52:29+00:00"
}
},
{
"labels": [
"Resource",
"Person",
"GraphGridResource"
],
"id": 343,
"properties": {
"createdAt": "2021-04-28T21:52:29+00:00",
"grn":
"grn:gg:person:pKMmKbKTseEGadwaM3EYOBrvKlTJpr5ICctdnfNYv4DP",
"lastSearchIndexedAt": "0",
"born": 1964,
"name": "Keanu Reeves",
"updatedAt": "2021-04-28T21:52:29+00:00"
}
}
]
}],
"bookmark": "neo4j:bookmark:v1:tx6495",
"errors": []
}
The response returns the shortest path between our two person nodes, which is that they both acted in "The Devil's Advocate." We can see and use our Showmes through the GraphGrid Dashboard. Now that we know more about the API calls, let's get a Showme working in the dashboard!
Showmes in The Dashboard
Getting Showmes to appear in the GraphGrid Dashboard takes some setup through GraphGrid Manager Models. A manager model shows what nodes, relationships, and properties are allowed and how they can be structured.
Setup Steps
These are the steps required to display a Showme in the dashboard:
Add Environment Triggers
Generate a Manager Model Policy
Get Manager Grn
Generate a Manager Model Graph
Create getNodeTypeGrns Showme
Execute getNodeTypeGrns Showme
Create your custom Showme
Add Environment Triggers
If you haven't already done so, be sure to run the /addTriggersForEnvironment
endpoint under Manager Environment. This prepares the
graph to accept the nodes and relationships that we'll be creating.
curl --location --request POST "${API_BASE}/1.0/manager/environment/addTriggersForEnvironment" \
--header "Authorization: Bearer ${BEARER_TOKEN}"
Generate a Manager Model Policy
A ManagerModelPolicy (MMP) is a JSON policy which is used to generate the NodeType, EdgeType, Property, PropertyImpl, and versioning
nodes of a manager model.
For our Movie Database we want to include the Movie and Person node labels.
curl --location --request POST "${API_BASE}/1.0/manager/model/policy/default/generateManagerPolicy/default-manager-model-policy" \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${BEARER_TOKEN}" \
--data-raw '{
"includeLabels":
[
"Person",
"Movie"
],
"excludeRelationships":[]
}'
Get Manager Grn
A manager node is automatically created when environment triggers are added to the graph. We need the manager grn in order to generate a manager model graph. This
request will get the manager by name and will return its grn. The default manager name is default
.
curl --location --request GET "${API_BASE}/1.0/manager/name/default" \
--header "Authorization: Bearer ${BEARER_TOKEN}"
Request response:
{
"manager": {
"id": 40,
"labels": [],
"enver": 0,
"createdAt": "2021-05-05T17:10:07+00:00",
"updatedAt": "2021-05-05T17:10:07+00:00",
"createdBy": "graphgrid",
"lastModifiedBy": "graphgrid",
"grn": "grn:gg:manager:t4fxJfDgJWRxFFO8PYS1hr7bHr0qQf68GHVuATR7B94X",
"name": "default",
"org": null,
"grnType": "manager",
"label": "Manager"
}
}
Generate a Manager Model Graph
Using our manager model policy and our manager node, we need to generate a manager model graph. This request essentially prepares our manager model policy to set up parameters that are required for the graph to recognize our nodetypes. The name of our manager model policy and our manager grn are required parameters for this request. Copy and paste the manager node grn from the response of the get manager request in the previous step.
curl --location --request POST "${API_BASE}/1.0/manager/model/policy/generateManagerModelGraph/default/default-manager-model-policy/grn:gg:manager:t4fxJfDgJWRxFFO8PYS1hr7bHr0qQf68GHVuATR7B94X' \
--header 'Content-Type: application/json" \
--header "Authorization: Bearer ${BEARER_TOKEN}"
Create getNodeTypeGrns Showme
A Showme needs to include the parameters nodeTypeGrns
and params
(or addParams
if created by the /updateShowMe
endpoint) for it
to be displayed in the dashboard. To easily retrieve the nodeTypeGrns
we can create a Showme that returns them as a list.
curl --location --request PUT
"${API_BASE}/1.0/showme/updateShowMe/getNodeTypeGrns" \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${BEARER_TOKEN}" \
--data-raw '{
"cypher": "UNWIND $nodeTypes AS nodeType WITH toLower(trim(nodeType)) AS nodeType MATCH (g:GraphGridNodeType) WHERE toLower(g.displayValue) = nodeType WITH COLLECT(g.grn) AS nodeTypeGrns RETURN REDUCE(s = HEAD(nodeTypeGrns), n IN TAIL(nodeTypeGrns) | '\''\"'\'' + n + '\''\"'\'' + '\'','\'' + '\''\"'\'' + s + '\''\"'\'') AS nodeTypeGrns;",
"showMePath" : "/getNodeTypeGrns",
"showMeMethod" : "POST",
"showMeDisplayValue" : "getNodeTypeGrns",
"showMeDefinition" : "getNodeTypeGrns",
"showMePopulatorDisplayValue" : "getNodeTypeGrns",
"showMePopulatorDefinition" : "getNodeTypeGrns",
"nodeTypeGrns" : [ ],
"params": { "nodeTypeGrns":[] }
}'
Execute getNodeTypeGrns Showme
Next we can execute our getNodeTypeGrns
Showme for our Person and Movie nodes.
curl --location --request POST "${API_BASE}/1.0/showme/executeShowMe/getNodeTypeGrns" \
--header "Authorization: Bearer ${BEARER_TOKEN}" \
--header 'Content-Type: application/json' \
--data-raw '{
"nodeTypes":["Person","Movie"]
}'
A successful response should look like this:
{
"results": [
{
"nodeTypeGrns":
"\"grn:gg:graphgridnodetype:p5m6SZLuqp5rTILpu1zOkVYFPY4x9FzjKIgAbgMPlS18\","\"grn:gg:graphgridnodetype:hRl8GplVHixGMQM1a4B6obNoOT00bhHVzpdOp59cgqDO\""
}
],
"bookmark": "neo4j:bookmark:v1:tx4145",
"errors": []
}
You can add these nodeTypeGrns
to any custom Showme in the request body under the nodeTypeGrns
key. For this tutorial we'll add it to the /shortestPath
Showme.
This is what the request looks like with the nodeTypeGrns
added to the Showme:
curl --location --request PUT "${API_BASE}/1.0/showme/updateShowMe/shortestPath" \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${BEARER_TOKEN}" \
--data-raw '{
"cypher": "MATCH (p1:Person) WHERE p1.grn = {firstPersonGrn} MATCH (p2:Person) WHERE p2.grn = {secondPersonGrn} MATCH p=allShortestPaths((p1)-[*]-(p2)) WHERE NONE(n IN nodes(p) WHERE n:Version) WITH nodes(p) AS shortestPathNodes UNWIND shortestPathNodes AS shortestPathNode RETURN COLLECT(shortestPathNode.grn) AS nodeIds",
"showMeMethod": "GET",
"showMePath": "/shortestPath",
"showMeDisplayValue": "shortestPath",
"showMeDefinition": "shortest path between two people",
"showMePopulatorDisplayValue": "shortestPath",
"showMePopulatorDefinition": "shortestPath",
"addNodeTypeGrns": ["grn:gg:graphgridnodetype:p5m6SZLuqp5rTILpu1zOkVYFPY4x9FzjKIgAbgMPlS18","grn:gg:graphgridnodetype:hRl8GplVHixGMQM1a4B6obNoOT00bhHVzpdOp59cgqDO"],
"addParams": {
"firstPersonGrn": "",
"secondPersonGrn": ""
},
"requiredParams": ["firstPersonGrn","secondPersonGrn"],
"cypherOrder": 0,
"overrideCypherOrder": false
}
'
Run the above request to update the /shortestPath
Showme with the proper nodeTypeGrns
.z
Create Your Custom Showme
Let's see our /shortestPath
Showme that we already created in action in the dashboard!
Viewing Showmes in the Dashboard
Before viewing the Showme in the dashboard run this Geequel query to remove the extra
resource nodes that are attached to the Showme result nodes.
MATCH (n) WHERE "Version" IN LABELS(n) OR "Manager" IN LABELS(n) OR "GraphGridNodeType" IN LABELS(n) REMOVE n:GraphGridResource
This will ensure that the
results will show only the relevant nodes and relationships between your parameters.
Head into the GraphGrid Dashboard and create a new project to display our Showme. In the query editor, run a query for 1 person node and add it to the graph. We used the "Al Pacino" node. Select the node and click the Showme button.
And the Showmes tab will appear:
From here you can edit the Showme in order to add parameters and run it.
The shortestPath Showme takes two parameters, firstPersonGrn
and secondPersonGrn
. Let's use a different grn from our original
shortestPath
request. Let's setfirstPersonGrn
to Carrie-Anne Moss and keep Al Pacino for the secondPersonGrn
. These parameters
will return the shortest path between these two actors who (according to the data we're using) have not acted in any movies together.
Once the parameters are set we can click the "Update Showme" button which will save our parameter values. Making sure our Al Pacino node is still selected, click the plus sign next to the name of the Showme.
Clicking this button will execute our Showme with our set parameters and will then appear in the graph.
Our Showme returned the shortest path between Al Pacino and Carrie-Anne Moss! Carrie-Anne starred in the "Matrix" Trilogy with Keanu Reeves who acted in "The Devil's Advocate" with Al Pacino.
Showme functionality within the UI is still a work in progress. In order to get the cleanest results from a Showme it's recommended to create a new project. If multiple Showmes are executed on the same project graph the results are added to the Showme nodes already displayed on the graph.