Skip to main content
Version: 1.4

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

  1. /getMoviesByYear Showme
    • Create a Showme called getMoviesByYear.
    • Execute the/getMoviesByYear Showme.
  2. /shortestPath Showme
    • Create a Showme called shortestPath
    • Execute the shortestPath Showme.
  3. 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 parameter released. 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:

note

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.

note

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

note

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.

Screenshot

And the Showmes tab will appear:

Screenshot

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.

Screenshot

Clicking this button will execute our Showme with our set parameters and will then appear in the graph.

Screenshot

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.

note

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.