| name | arcgis-knowledge-graphs |
| description | Work with ArcGIS Knowledge graphs for storing and querying connected data. Use for graph databases, relationship visualization, and openCypher queries. |
ArcGIS Knowledge Graphs
Use this skill for working with knowledge graphs, graph queries, and relationship visualization.
Knowledge Graph Service
Fetch Knowledge Graph
import KGModule from "@arcgis/core/rest/knowledgeGraphService.js";
const url = "https://your-server/server/rest/services/Hosted/YourKG/KnowledgeGraphServer";
const knowledgeGraph = await KGModule.fetchKnowledgeGraph(url);
console.log("Graph name:", knowledgeGraph.name);
console.log("Entity types:", knowledgeGraph.dataModel.entityTypes);
console.log("Relationship types:", knowledgeGraph.dataModel.relationshipTypes);
KnowledgeGraphLayer
Add to Map
import KnowledgeGraphLayer from "@arcgis/core/layers/KnowledgeGraphLayer.js";
const kgLayer = new KnowledgeGraphLayer({
url: "https://your-server/server/rest/services/Hosted/YourKG/KnowledgeGraphServer"
});
await kgLayer.load();
map.add(kgLayer);
Configure Sublayers
const kgLayer = new KnowledgeGraphLayer({
url: "...",
// Only include specific entity types
inclusionModeDefinition: {
generateAllSublayers: false,
namedTypeDefinitions: new Map([
["Person", { useAllData: true }],
["Location", { useAllData: true }]
])
}
});
Querying with openCypher
Basic Query
import KGModule from "@arcgis/core/rest/knowledgeGraphService.js";
const result = await KGModule.executeQuery(knowledgeGraph, {
openCypherQuery: "MATCH (n:Person) RETURN n LIMIT 10"
});
console.log("Results:", result.resultRows);
Streaming Query (Large Results)
const queryResults = await KGModule.executeQueryStreaming(knowledgeGraph, {
openCypherQuery: "MATCH (n:Person)-[r]->(m) RETURN n, r, m"
});
// Read stream
const reader = queryResults.resultRowsStream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Process chunk
value.forEach(row => {
console.log("Row:", row);
});
}
Spatial Query with Bind Parameters
import KGModule from "@arcgis/core/rest/knowledgeGraphService.js";
import Polygon from "@arcgis/core/geometry/Polygon.js";
// Create geometry for spatial filter
const searchArea = new Polygon({
rings: [[
[-76, 45],
[-70, 45],
[-70, 40],
[-76, 40],
[-76, 45]
]]
});
const queryResults = await KGModule.executeQueryStreaming(knowledgeGraph, {
openCypherQuery: `
MATCH path=(a:User)-[]->(b:Observation)
WHERE esri.graph.ST_Intersects($geometry, b.shape)
RETURN path
`,
bindParameters: {
geometry: searchArea
}
});
Query with Filters
// Filter by property
const result = await KGModule.executeQuery(knowledgeGraph, {
openCypherQuery: `
MATCH (p:Person)
WHERE p.age > 30 AND p.name CONTAINS 'John'
RETURN p
`
});
// Query relationships
const result = await KGModule.executeQuery(knowledgeGraph, {
openCypherQuery: `
MATCH (p:Person)-[r:WORKS_AT]->(c:Company)
WHERE c.name = 'Esri'
RETURN p.name, r.startDate, c.name
`
});
Link Chart Visualization
Create Link Chart
import WebLinkChart from "@arcgis/core/WebLinkChart.js";
import LinkChartView from "@arcgis/core/views/LinkChartView.js";
import LinkChartLayer from "@arcgis/core/layers/LinkChartLayer.js";
const linkChartLayer = new LinkChartLayer({
url: "https://your-server/.../KnowledgeGraphServer"
});
const linkChart = new WebLinkChart({
layers: [linkChartLayer]
});
const linkChartView = new LinkChartView({
container: "linkChartDiv",
map: linkChart
});
LinkChartView Configuration
const linkChartView = new LinkChartView({
container: "linkChartDiv",
map: linkChart,
// Enable interaction
highlightOptions: {
color: [0, 255, 255, 1],
haloColor: [0, 255, 255, 0.5],
haloOpacity: 0.8
},
// Navigation
navigation: {
mouseWheelZoomEnabled: true,
browserTouchPanEnabled: true
}
});
// View events
linkChartView.on("click", async (event) => {
const response = await linkChartView.hitTest(event);
if (response.results.length > 0) {
const graphic = response.results[0].graphic;
console.log("Clicked:", graphic.attributes);
}
});
// Watch for selection changes
linkChartView.on("selection-change", (event) => {
console.log("Selected entities:", event.added);
console.log("Deselected entities:", event.removed);
});
Link Chart Component
<arcgis-link-chart>
<arcgis-legend slot="top-right"></arcgis-legend>
<arcgis-zoom slot="bottom-right"></arcgis-zoom>
</arcgis-link-chart>
<script type="module">
const linkChartComponent = document.querySelector("arcgis-link-chart");
await linkChartComponent.componentOnReady();
const lcView = linkChartComponent.view;
const linkChart = lcView.map;
// Add records to link chart
linkChart.addRecords([
{ id: "entity1", typeName: "Person" },
{ id: "entity2", typeName: "Company" }
]);
</script>
Link Chart Layout Settings
// Access layout settings
const layoutSettings = linkChart.layoutSettings;
// Organic Layout (default)
linkChart.layoutSettings = {
type: "organic",
avoidLabelOverlap: true,
compactness: 0.5, // 0-1, how tightly packed
orientation: "top-to-bottom" // top-to-bottom, bottom-to-top, left-to-right, right-to-left
};
// Chronological Layout
linkChart.layoutSettings = {
type: "chronological",
dateField: "timestamp",
groupByField: "category",
orientation: "horizontal", // horizontal, vertical
showTimeline: true
};
OrganicLayoutSettings
import OrganicLayoutSettings from "@arcgis/core/webdoc/applicationProperties/OrganicLayoutSettings.js";
const organicLayout = new OrganicLayoutSettings({
avoidLabelOverlap: true,
compactness: 0.6,
componentLayoutEnabled: true,
deterministic: true,
minimumNodeDistance: 50,
orientation: "top-to-bottom",
preferredEdgeLength: 100,
starSubstructureEnabled: true,
treeSubstructureEnabled: true
});
linkChart.layoutSettings = organicLayout;
ChronologicalLayoutSettings
import ChronologicalLayoutSettings from "@arcgis/core/webdoc/applicationProperties/ChronologicalLayoutSettings.js";
const chronoLayout = new ChronologicalLayoutSettings({
dateField: "event_date",
groupByField: "event_type",
orientation: "horizontal",
showTimeline: true,
timelinePosition: "bottom",
sortOrder: "ascending" // ascending, descending
});
linkChart.layoutSettings = chronoLayout;
LinkChartLayoutSwitcher Widget
import LinkChartLayoutSwitcher from "@arcgis/core/widgets/LinkChartLayoutSwitcher.js";
const layoutSwitcher = new LinkChartLayoutSwitcher({
view: linkChartView,
layouts: [
{
name: "Organic",
settings: new OrganicLayoutSettings({ compactness: 0.5 })
},
{
name: "Timeline",
settings: new ChronologicalLayoutSettings({ dateField: "date" })
}
]
});
linkChartView.ui.add(layoutSwitcher, "top-right");
Non-Spatial Data Display
// Configure non-spatial display for entities
const linkChartLayer = new LinkChartLayer({
url: "...",
nonspatialDataDisplay: {
entityTypes: {
Person: {
displayField: "name",
symbol: {
type: "simple-marker",
color: "blue",
size: 20
}
},
Company: {
displayField: "company_name",
symbol: {
type: "simple-marker",
color: "green",
size: 25
}
}
},
relationshipTypes: {
WORKS_AT: {
symbol: {
type: "simple-line",
color: "gray",
width: 2
}
}
}
}
});
Adding and Removing Records
// Add records
await linkChart.addRecords([
{ id: "person-1", typeName: "Person" },
{ id: "company-1", typeName: "Company" },
{ id: "rel-1", typeName: "WORKS_AT" }
]);
// Remove records
await linkChart.removeRecords([
{ id: "person-1", typeName: "Person" }
]);
// Clear all records
await linkChart.removeAllRecords();
// Get current records
const records = linkChart.records;
console.log("Current entities:", records.entities);
console.log("Current relationships:", records.relationships);
Update Link Chart from Query Results
async function updateLinkChart(queryResults, linkChart) {
const reader = queryResults.resultRowsStream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const records = [];
for (const row of value) {
for (const record of row[0].path) {
records.push({
id: record.id,
typeName: record.typeName
});
}
}
linkChart.addRecords(records);
}
}
Expand/Collapse Entities
// Expand entity to show connections
await linkChart.expand({
ids: ["entity-id"],
typeName: "Person",
relationshipTypes: ["KNOWS", "WORKS_AT"],
direction: "both" // outgoing, incoming, both
});
// Collapse entity
await linkChart.collapse({
ids: ["entity-id"],
typeName: "Person"
});
Selection and Highlighting
// Select entities programmatically
linkChartView.select([
{ id: "person-1", typeName: "Person" },
{ id: "person-2", typeName: "Person" }
]);
// Clear selection
linkChartView.clearSelection();
// Highlight (temporary visual emphasis)
const highlightHandle = linkChartView.highlight([
{ id: "person-1", typeName: "Person" }
]);
// Remove highlight
highlightHandle.remove();
// Go to specific entities
linkChartView.goTo([
{ id: "person-1", typeName: "Person" }
]);
WebLinkChart Properties
import WebLinkChart from "@arcgis/core/WebLinkChart.js";
const webLinkChart = new WebLinkChart({
// Portal item (load existing)
portalItem: { id: "LINKCHART_ID" },
// Or create from scratch
layers: [linkChartLayer],
// Layout settings
layoutSettings: organicLayout,
// Initial records
initialRecords: {
entities: [
{ id: "entity-1", typeName: "Person" }
],
relationships: []
}
});
// Save to portal
await webLinkChart.saveAs({
title: "My Link Chart",
snippet: "Visualization of entity relationships"
});
Search Knowledge Graph
import KGModule from "@arcgis/core/rest/knowledgeGraphService.js";
const searchResults = await KGModule.executeSearch(knowledgeGraph, {
searchQuery: "John Smith",
typeCategoryFilter: "entity", // or "relationship", "both"
typeNames: ["Person", "Employee"],
returnSearchContext: true
});
searchResults.results.forEach(result => {
console.log("Found:", result.typeName, result.id);
console.log("Context:", result.searchContext);
});
Apply Edits
import KGModule from "@arcgis/core/rest/knowledgeGraphService.js";
// Add entity
const addResult = await KGModule.executeApplyEdits(knowledgeGraph, {
entityAdds: [{
typeName: "Person",
properties: {
name: "Jane Doe",
age: 28
}
}]
});
// Update entity
const updateResult = await KGModule.executeApplyEdits(knowledgeGraph, {
entityUpdates: [{
typeName: "Person",
properties: {
globalId: "{existing-global-id}",
age: 29
}
}]
});
// Delete entity
const deleteResult = await KGModule.executeApplyEdits(knowledgeGraph, {
entityDeletes: [{
typeName: "Person",
ids: ["{global-id-to-delete}"]
}]
});
// Add relationship
const relResult = await KGModule.executeApplyEdits(knowledgeGraph, {
relationshipAdds: [{
typeName: "WORKS_AT",
properties: {
originGlobalId: "{person-global-id}",
destinationGlobalId: "{company-global-id}",
startDate: new Date()
}
}]
});
Data Model
// Access data model
const dataModel = knowledgeGraph.dataModel;
// Entity types
dataModel.entityTypes.forEach(entityType => {
console.log("Entity:", entityType.name);
console.log("Properties:", entityType.properties);
});
// Relationship types
dataModel.relationshipTypes.forEach(relType => {
console.log("Relationship:", relType.name);
console.log("Origin:", relType.originEntityTypes);
console.log("Destination:", relType.destinationEntityTypes);
});
Common openCypher Patterns
-- Find all entities
MATCH (n) RETURN n
-- Find specific type
MATCH (p:Person) RETURN p
-- Find relationships
MATCH (a)-[r]->(b) RETURN a, r, b
-- Find path
MATCH path = (a:Person)-[:KNOWS*1..3]->(b:Person)
WHERE a.name = 'John'
RETURN path
-- Aggregate
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
RETURN c.name, COUNT(p) as employeeCount
-- Spatial filter
MATCH (loc:Location)
WHERE esri.graph.ST_Intersects($geometry, loc.shape)
RETURN loc
Common Pitfalls
Authentication required: Knowledge graph services typically require authentication
Streaming for large results: Use
executeQueryStreamingfor queries that may return many resultsGeometry conversion: Convert geometries to WGS84 before using in spatial queries
Case sensitivity: openCypher property names are case-sensitive