NetworkGraph
The NetworkGraph widget displays relationships between entities. The relationships are displayed as nodes connected by lines. A configuration allows users to filter the nodes displayed in the graph.
NetworkGraph MarkLogic setup
The NetworkGraph widget displays graphs showing relationships from MarkLogic result sets. For example, the result sets from the /v1/search
and /v1/graphs/sparql
endpoints from the MarkLogic REST API can be graphed using the widget.
In order to display triples from /v1/search
results, the content must be extracted and included in the search results. This can be done by using the extract-document-data
property in the query options in the application. For more information, see Include document extracts in search results.
Note
To use the /v1/graphs/sparql
endpoint to execute SPARQL queries on triples and display the SPARQL results as a graph, the database triples index must be turned on.
Graph data model
To configure the NetworkGraph widget, an object with key/value pairs is provided that represents nodes and links in the graph. Each node and link have a unique key with a value object that determines how they appear in the graph. Link objects have id1
and id2
properties that use node keys as their values. The node keys determine the source and destination of each link.
In this example, the NetworkGraph widget configuration object has three nodes and three links. The configuration object is passed into NetworkGraph
using the items
prop. Additional configuration values are passed into the widget using the settings
prop. The options
object turns on navigation buttons (navigation: true)
and sets the canvas background to white (backgroundColor: 'white')
.
For more information, see the third-party documentation included with FastTrack.
import { NetworkGraph } from "ml-fasttrack"; function App() { const items = { node1: { label: [{ text: 'My Node 1' }] }, node2: { label: [{ text: 'My Node 2' }] }, node3: { label: [{ text: 'My Node 3' }] }, link1: { id1: 'node1', id2: 'node2' }, link2: { id1: 'node1', id2: 'node3' }, link3: { id1: 'node3', id2: 'node1', } }; const settings = { options: { navigation: true, backgroundColor: 'white', } }; return ( <div> <NetworkGraph items={items} settings={{ options: { backgroundColor: "white", navigation: true, } }} />; </div> ); } export default App;
Note
The example displays nodes and graphs in NetworkGraph by defining them directly in an items
object. The example does not transform data from MarkLogic into an object.
The next sections describe how to transform MarkLogic data and display it in a graph. The configuration displays the NetworkGraph example rendering.
NetworkGraph example rendering
In this example, one link goes from My Node 1 to My Node 2, another goes from My Node 1 to My Node 3, and a third goes from My Node 3 to My Node 1. Labels are added to the nodes as part of the node configuration.
There are many other configuration options for the nodes, links, and graph canvas.
For more information, see the third-party documentation included with FastTrack.
Graph search results with entityConfig
Relationship data from embedded triples in /v1/search
results can be displayed as a graph. This is accomplished using the data
and entityConfig
props. The data
prop is set to the /v1/search
response. The entityConfig
prop maps responses to the graph. This strategy assumes that:
Documents in the search results represent entity instances that will be represented as nodes in the graph. Node URIs are used as node keys.
Document URIs can be derived from the relationship triples embedded in the documents. If the data is modeled differently, refer to Graph results with transforms to transform relationship data.
In this example, the subject, predicate, and object are graphed from each embedded triple in a /v1/search
response. The search response looks like this:
{ "snippet-format": "snippet", "total": 3, "start": 1, "page-length": 10, "results": [ { "index": 1, "uri": "/person/1001.json", "path": "fn:doc(\"/person/1001.json\")", "extracted": { "kind": "array", "content": [ { "envelope": { "entityType": "person", "id": 1001, "firstName": "Nerta", "lastName": "Hallwood", "address": { "state": "Texas", "country": "United States" }, "relations": [ { "triple": { "subject": "http://example.org/person/1001.json", "predicate": "http://xmlns.com/foaf/0.1/knows/", "object": "http://example.org/person/1002.json" } }, { "triple": { "subject": "http://example.org/person/1001.json", "predicate": "http://xmlns.com/foaf/0.1/knows/", "object": "http://example.org/person/1003.json" } } ] } } ] } }, // more results ], "qtext": "person", }
Each search result includes a document extract with semantic triples. The subject
and object
values in the triples include the URIs of the entities they relate to. Each search result also includes the entityType
for the entity instance. In this example, entityType
is set to person
.
The NetworkGraph widget can be configured to display entity instances as nodes in the graph. Links represent the triple relationships.
NetworkGraph example configuration
A React application with the NetworkGraph widget and entityConfig
and data
props looks like this:
import { useContext } from "react"; import "./App.css"; import { MarkLogicContext, SearchBox, NetworkGraph } from "ml-fasttrack"; function App() { const context = useContext(MarkLogicContext); const handleSearch = (params) => { context.setQtext(params?.q); } const entityConfig = { entityTypeConfig: { "path": "extracted.content[0].envelope.entityType" }, entities: [ { entityType: "person", triples: { path: "extracted.content[0].envelope.relations", subject: { path: "triple.subject", regex: /\/\w+\/[^/]+$/ }, predicate: { path: "triple.predicate" }, object: { path: "triple.object", regex: /\/\w+\/[^/]+$/ } }, items: { label: [ { text: { path: "extracted.content[0].envelope.firstName" } } ] }, nodeRelations: { relationLabelRgx: /(\w+)$/ } } ] } return ( <div className="App"> <div> <SearchBox onSearch={handleSearch}/> </div> <div> <NetworkGraph data={context?.searchResponse} entityConfig={entityConfig} /> </div> </div> ); } export default App;
Code explanation
Notes on the NetworkGraph example configuration:
To make the MarkLogic search response available to the NetworkGraph widget, the
data
prop is assigned thesearchResponse
value from the application context.The
entityConfig
prop accepts a configuration object that tells the widget how to build the data model for the underlying graph from the response data.The path values in the configuration object map the data in the search response payload to the graph data model.
Regex props can be used to select parts of the triple values to use in the graph. This example uses the regex values to extract the URIs from the subject and object values. For more details about the configuration props, see NetworkGraph API
NetworkGraph example rendering
The NetworkGraph example configuration generates this graph:
Node labels are defined in the firstName
property from each entity instance and are configured with the entities[].items property
. The link label is extracted from the predicate
value in each triple using the regex in the nodeRelations
property.
Graph results with transforms
Data from SPARQL results and other types of payloads can be transformed into the data model expected by the graph widget. Then, the data can be passed to the NetworkGraph widget as an items
prop.
This example shows a React application using a SPARQL query and the transformation strategy:
import { useContext, useEffect } from "react"; import "./App.css"; import { MarkLogicContext, NetworkGraph } from "ml-fasttrack"; function App() { const context = useContext(MarkLogicContext); const sparqlQuery = ` SELECT (str(?subName) as ?s) ?p (str(?objName) as ?o) (str(?subState) as ?sState) (str(?objState) as ?oState) WHERE { ?subject ?predicate ?object . ?subject <http://xmlns.com/foaf/0.1/knows> ?object . ?subject <http://example.org/firstName> ?subName . ?object <http://example.org/firstName> ?objName . ?subject <http://example.org/state> ?subState . ?object <http://example.org/state> ?objState . BIND (SUBSTR(?predicate,27,5) AS ?p) } ` const sparqlToItems = (sparqlResponse) => { if (!sparqlResponse) return; let items = {}; sparqlResponse.results.bindings.forEach(r => { const { s, p, o } = r // create subject node if (s && s?.value) { items[s.value] = { label: [{ text: s?.value }], } } // create object node if (o && o?.value) { items[o.value] = { label: [{ text: o?.value }], } } // create predicate link if (s && s?.value && o && o?.value) { items[s.value + '-' + o.value] = { id1: s.value, id2: o.value, label: { text: p?.value }, } } }) return items; } useEffect(() => { context.getSparql(sparqlQuery); }, []); return ( <div className="App"> <div> <NetworkGraph items={sparqlToItems(context.sparqlResponse)} onSelectNode={(event) => console.log(event)} /> </div> </div> ); } export default App;
Code explanation
In Graph results with transforms:
The SPARQL query is used on the
/v1/graphs/sparql
endpoint using thegetSparql
method from the application context. The query is defined in thesparqlQuery
variable.The query is executed on load using a
useEffect
hook and thegetSparql
method from the application context.The SPARQL result is stored in
context.sparqlResponse
by the application context.To transform the MarkLogic SPARQL response into the data model expected by the graph widget, a
sparqlToItems
function is used. It is a custom function that accesses the bindings in a SPARQL response to build nodes and links.The
onSelectNode
prop is passed a callback to handle node selection events.
Graph results with transforms example rendering
The code in Graph results with transforms generates this graph. Clicking a node in the graph logs the click event to the console.
Styling nodes and links
Styles can be applied to nodes and links in the graph by adding properties. The examples in this section illustrate how to:
change the color and size of nodes.
change the color and width of links.
turn on link arrows.
If the entityConfig strategy is used for mapping, additional properties can be added to the entityConfig
object under the entities[].items
and entities[].nodeRelations
properties:
const entityConfig = { entityTypeConfig: { "path": "extracted.content[0].envelope.entityType" }, entities: [ { entityType: "person", triples: { path: "extracted.content[0].envelope.relations", subject: { path: "triple.subject", regex: /\/\w+\/[^/]+$/ }, predicate: { path: "triple.predicate" }, object: { path: "triple.object", regex: /\/\w+\/[^/]+$/ } }, items: { color: "red", size: 2, label: [ { text: { path: "extracted.content[0].envelope.firstName" } } ] }, nodeRelations: { relationLabelRgx: /(\w+)$/, link: { width: 10, color: "orange", end1: { arrow: false }, end2: { arrow: true } } } } ] }
If a transformation function is used for mapping, the style properties can be set for each subject, predicate, and object in the function:
const sparqlToItems = (sparqlResponse) => { if (!sparqlResponse) return; let items = {}; sparqlResponse.results.bindings.forEach(r => { const { s, p, o } = r if (s && s?.value) { items[s.value] = { label: [{ text: s?.value }], color: "red", size: 2 } } if (o && o?.value) { items[o.value] = { label: [{ text: o?.value }], color: "red", size: 2 } } if (s && s?.value && o && o?.value) { items[s.value + '-' + o.value] = { id1: s.value, id2: o.value, label: { text: p?.value }, width: 3, color: "orange", end1: { arrow: false }, end2: { arrow: true } } } }) return items; }
Styling the nodes and links using the additional properties displays this graph:
For more information, see the third-party documentation included with FastTrack.
Filter nodes
Nodes in the graph can be filtered. To filter nodes, include properties for the filter in each node's configuration. If the entityConfig strategy is used to show search results as a graph, include a filters
object with key/value pairs. The key/values pairs should specify the path to the result property. This example includes the state address in each node configuration with the key stateVal
:
const entityConfig = { entityTypeConfig: { "path": "extracted.content[0].envelope.entityType" }, entities: [ { entityType: "person", triples: { path: "extracted.content[0].envelope.relations", subject: { path: "triple.subject", regex: /\/\w+\/[^/]+$/ }, predicate: { path: "triple.predicate" }, object: { path: "triple.object.value", regex: /\/\w+\/[^/]+$/ } }, filters: { stateVal: { path: 'extracted.content[0].envelope.address.state' }, }, nodeRelations: { relationLabelRgx: /(\w+)$/ } } ] }
Custom transformation functions can include filter properties in each node configuration. In this example SPARQL query, state values for the subjects and objects are included as the sState
and oState
bindings. These bindings can then be accessed in order to put the state values in the subject and object node configurations:
const sparqlToItems = (sparqlResponse) => { if (!sparqlResponse) return; let items = {}; sparqlResponse.results.bindings.forEach(r => { const { s, p, o, sState, oState } = r if (s && s?.value) { items[s.value] = { label: [{ text: s?.value }], stateVal: sState.value } } if (o && o?.value) { items[o.value] = { label: [{ text: o?.value }], stateVal: oState.value } } if (s && s?.value && o && o?.value) { items[s.value + '-' + o.value] = { id1: s.value, id2: o.value, label: { text: p?.value }, } } }) return items; }
Once the filter values are present in the node configuration objects, a filter list can be configured in the NetworkGraph widget with a filterConfig
prop:
<NetworkGraph data={context?.searchResponse} entityConfig={graphConfig} filterConfig={[ { label: 'State', path: 'stateVal' } ]} />
Code explanation
In the Filter nodes example:
Each object in the
filterConfig
array defines a filter list. This example defines a single filter list for thestate
property.The
label
value specifies the list title.The
path
value references the property in the node object. This path value can be the key from the filter's configuration object (in this case,stateVal
) or a dot-notated path from the key if the value in the node object is an object.
Filter nodes example rendering
Adding a filter list to the NetworkGraph using the example code in Filter nodes displays:
Users can click the check boxes to limit the nodes displayed.
NetworkGraph API
Prop |
Type |
Description |
---|---|---|
items |
object |
Items to display in the graph. Each node and relation are defined with a property and object value. For more information, see the third-party documentation included with FastTrack. NoteNodes and links can be defined in the graph directly using the |
data |
object |
Search results payload to display in the graph. This works in conjunction with the |
dataConfig |
object |
Optional JSONPath for indicating the results in the data prop. |
entityConfig |
object |
Entity-specific configuration settings for the subject, predicate, and object values, labels, and styles in the graph. For more information, see the third-party documentation included with FastTrack. |
showMap |
boolean |
Show the map in the canvas with Leaflet. Requires a coordinates object. For more information, see the third-party documentation included with FastTrack. |
settings |
Record<string, any> |
Configuration props passed in for the graph, including canvas options, event handlers, and other properties (such as adding a reference to manage adjustments in the view). For more information, see the third-party documentation included with FastTrack. |
height |
string |
Height of the widget canvas as a CSS height value. Default is |
width |
string |
Width of the widget canvas as a CSS width value. Default is |
relationsLevel |
number |
Relations level for filtering. |
selectedElement |
string |
ID of the selected element. |
filterConfig |
{ id: string; label: string; path: string; }[] |
Configuration settings for the graph filter. |
fontFamilies |
string[] |
Array of font families. Example name: "Font Awesome 5 Free". |
nodeConfig |
object |
Default settings for a node when it is not defined in |
relationConfig |
object |
Default settings for a relation link when it is not defined in entityConfig. |
itemsTooltipConfig |
object |
Configuration object that maps and formats a tooltip for a node when not defined in |
onSelectNode |
((node: any) => void) |
Callback function triggered when a node is clicked. |
onDoubleClickNode |
((node: any) => void) |
Callback function triggered when a node is double-clicked. |
entityConfig API
Property |
Type |
Description |
---|---|---|
entityTypeConfig |
object |
Entity type configuration object. |
entityTypeConfig.path |
string |
Path to the entity type in the search result. The path is specified using JSONPath . |
entities[] |
object[] |
Array of graph configuration objects for each entity. |
entities[].entityType |
string |
Entity type of the configuration object. |
entities[].triples |
object |
Triples configuration object. |
entities[].triples.path |
string |
Path to the array of triples. The path is specified using JSONPath. |
entities[].triples.subject |
object |
Triple subject configuration object. |
entities[].triples.subject.path |
string |
Path to the subject value relative to the triples path. The path is specified using JSONPath. |
entities[].triples.subject.regex |
regex |
Optional regex with which to select a part of the subject value. |
entities[].triples.predicate |
object |
Triple predicate configuration object. |
entities[].triples.predicate.path |
string |
Path to the predicate value relative to the triples path. The path is specified using JSONPath. |
entities[].triples.object |
object |
Triple object configuration object. |
entities[].triples.object.path |
string |
Path to the object value relative to the triples path. The path is specified using JSONPath. |
entities[].triples.object.regex |
regex |
Optional regex with which to select a part of the object value. |
entities[].items |
object |
Styles and formatting applied to the nodes. For more information, see the third-party documentation included with FastTrack. |
entities[].nodeRelations.relationLabelRgx |
string |
Optional regex with which to select a part of the predicate value as a link label. |
entities[].nodeRelations.link |
object |
Styles and formatting applied to the links. For more information, see the third-party documentation included with FastTrack. |
entities[].tooltipConfig |
object |
Configuration object that maps and formats a tooltip for a node. |
entities[].filters |
object |
Configuration object that defines extra values to include in the node objects. The values are used for filtering. |