skills/arcgis-knowledge-graphs/SKILL.md
Work with ArcGIS Knowledge graphs for storing, querying, and visualizing connected data using KnowledgeGraphLayer, LinkChartView, and openCypher queries. Use for graph databases, relationship visualization, and entity exploration.
npx skillsauth add SaschaBrunnerCH/arcgis-maps-sdk-js-ai-context arcgis-knowledge-graphsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill for knowledge graphs, graph queries (openCypher), link chart visualization, and entity-relationship management.
// Knowledge graph service
import * as knowledgeGraphService from "@arcgis/core/rest/knowledgeGraphService.js";
// Layers
import KnowledgeGraphLayer from "@arcgis/core/layers/KnowledgeGraphLayer.js";
import LinkChartLayer from "@arcgis/core/layers/LinkChartLayer.js";
// Views and charts
import WebLinkChart from "@arcgis/core/WebLinkChart.js";
import LinkChartView from "@arcgis/core/views/LinkChartView.js";
// Layout settings
import OrganicLayoutSettings from "@arcgis/core/linkChart/OrganicLayoutSettings.js";
import ChronologicalLayoutSettings from "@arcgis/core/linkChart/ChronologicalLayoutSettings.js";
import LinkChartLayoutSwitcher from "@arcgis/core/linkChart/LinkChartLayoutSwitcher.js";
const knowledgeGraphService = await $arcgis.import(
"@arcgis/core/rest/knowledgeGraphService.js",
);
const KnowledgeGraphLayer = await $arcgis.import(
"@arcgis/core/layers/KnowledgeGraphLayer.js",
);
const WebLinkChart = await $arcgis.import("@arcgis/core/WebLinkChart.js");
const LinkChartView = await $arcgis.import(
"@arcgis/core/views/LinkChartView.js",
);
const url =
"https://your-server/server/rest/services/Hosted/YourKG/KnowledgeGraphServer";
const knowledgeGraph = await knowledgeGraphService.fetchKnowledgeGraph(url);
console.log("Graph name:", knowledgeGraph.name);
console.log("Entity types:", knowledgeGraph.dataModel.entityTypes);
console.log("Relationship types:", knowledgeGraph.dataModel.relationshipTypes);
| Function | Description |
| ----------------------------------- | ------------------------------------------------- |
| fetchKnowledgeGraph(url) | Fetch knowledge graph metadata and data model |
| executeQuery(kg, params) | Execute openCypher query, return all results |
| executeQueryStreaming(kg, params) | Stream large query results |
| executeSearch(kg, params) | Full-text search across entities |
| executeApplyEdits(kg, params) | Add, update, or delete entities and relationships |
const kgLayer = new KnowledgeGraphLayer({
url: "https://your-server/server/rest/services/Hosted/YourKG/KnowledgeGraphServer",
});
await kgLayer.load();
map.add(kgLayer);
const kgLayer = new KnowledgeGraphLayer({
url: "...",
inclusionModeDefinition: {
generateAllSublayers: false,
namedTypeDefinitions: new Map([
["Person", { useAllData: true }],
["Location", { useAllData: true }],
]),
},
});
const result = await knowledgeGraphService.executeQuery(knowledgeGraph, {
openCypherQuery: "MATCH (n:Person) RETURN n LIMIT 10",
});
console.log("Results:", result.resultRows);
const queryResults = await knowledgeGraphService.executeQueryStreaming(
knowledgeGraph,
{
openCypherQuery: "MATCH (n:Person)-[r]->(m) RETURN n, r, m",
},
);
const reader = queryResults.resultRowsStream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
value.forEach((row) => {
console.log("Row:", row);
});
}
import Polygon from "@arcgis/core/geometry/Polygon.js";
const searchArea = new Polygon({
rings: [
[
[-76, 45],
[-70, 45],
[-70, 40],
[-76, 40],
[-76, 45],
],
],
});
const queryResults = await knowledgeGraphService.executeQueryStreaming(
knowledgeGraph,
{
openCypherQuery: `
MATCH path=(a:User)-[]->(b:Observation)
WHERE esri.graph.ST_Intersects($geometry, b.shape)
RETURN path
`,
bindParameters: {
geometry: searchArea,
},
},
);
// Filter by property
const result = await knowledgeGraphService.executeQuery(knowledgeGraph, {
openCypherQuery: `
MATCH (p:Person)
WHERE p.age > 30 AND p.name CONTAINS 'John'
RETURN p
`,
});
// Query relationships
const result = await knowledgeGraphService.executeQuery(knowledgeGraph, {
openCypherQuery: `
MATCH (p:Person)-[r:WORKS_AT]->(c:Company)
WHERE c.name = 'Esri'
RETURN p.name, r.startDate, c.name
`,
});
-- Find all entities of a type
MATCH (p:Person) RETURN p
-- Find relationships
MATCH (a)-[r]->(b) RETURN a, r, b
-- Find path with depth
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
const searchResults = await knowledgeGraphService.executeSearch(
knowledgeGraph,
{
searchQuery: "John Smith",
typeCategoryFilter: "entity", // "entity", "relationship", "both"
typeNames: ["Person", "Employee"],
returnSearchContext: true,
},
);
searchResults.results.forEach((result) => {
console.log("Found:", result.typeName, result.id);
console.log("Context:", result.searchContext);
});
// Add entity
await knowledgeGraphService.executeApplyEdits(knowledgeGraph, {
entityAdds: [
{
typeName: "Person",
properties: { name: "Jane Doe", age: 28 },
},
],
});
// Update entity
await knowledgeGraphService.executeApplyEdits(knowledgeGraph, {
entityUpdates: [
{
typeName: "Person",
properties: { globalId: "{existing-global-id}", age: 29 },
},
],
});
// Delete entity
await knowledgeGraphService.executeApplyEdits(knowledgeGraph, {
entityDeletes: [
{
typeName: "Person",
ids: ["{global-id-to-delete}"],
},
],
});
// Add relationship
await knowledgeGraphService.executeApplyEdits(knowledgeGraph, {
relationshipAdds: [
{
typeName: "WORKS_AT",
properties: {
originGlobalId: "{person-global-id}",
destinationGlobalId: "{company-global-id}",
startDate: new Date(),
},
},
],
});
const dataModel = knowledgeGraph.dataModel;
dataModel.entityTypes.forEach((entityType) => {
console.log("Entity:", entityType.name);
console.log("Properties:", entityType.properties);
});
dataModel.relationshipTypes.forEach((relType) => {
console.log("Relationship:", relType.name);
console.log("Origin:", relType.originEntityTypes);
console.log("Destination:", relType.destinationEntityTypes);
});
const linkChartLayer = new LinkChartLayer({
url: "https://your-server/.../KnowledgeGraphServer",
});
const linkChart = new WebLinkChart({
layers: [linkChartLayer],
});
const linkChartView = new LinkChartView({
container: "linkChartDiv",
map: linkChart,
highlightOptions: {
color: [0, 255, 255, 1],
haloColor: [0, 255, 255, 0.5],
haloOpacity: 0.8,
},
});
<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;
await linkChart.addRecords([
{ id: "entity1", typeName: "Person" },
{ id: "entity2", typeName: "Company" },
]);
</script>
// 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" }]);
await linkChart.expand({
ids: ["entity-id"],
typeName: "Person",
relationshipTypes: ["KNOWS", "WORKS_AT"],
direction: "both", // "outgoing", "incoming", "both"
});
linkChartView.goTo([{ id: "person-1", typeName: "Person" }]);
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);
}
});
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,
});
}
}
await linkChart.addRecords(records);
}
}
const organicLayout = new OrganicLayoutSettings();
linkChart.layoutSettings = organicLayout;
const chronoLayout = new ChronologicalLayoutSettings();
linkChart.layoutSettings = chronoLayout;
const layoutSwitcher = new LinkChartLayoutSwitcher({
view: linkChartView,
});
linkChartView.ui.add(layoutSwitcher, "top-right");
<arcgis-link-chart>
<arcgis-link-chart-layout-switcher
slot="top-right"
></arcgis-link-chart-layout-switcher>
</arcgis-link-chart>
const webLinkChart = new WebLinkChart({
portalItem: { id: "LINKCHART_ID" },
layoutSettings: organicLayout,
});
// Save to portal
await webLinkChart.saveAs({
title: "My Link Chart",
snippet: "Visualization of entity relationships",
});
Authentication required: Knowledge graph services typically require authentication — configure credentials or OAuth.
Streaming for large results: Use executeQueryStreaming for queries that may return many results; executeQuery loads everything into memory.
Geometry conversion: Convert geometries to WGS84 before using in spatial queries with esri.graph.ST_Intersects.
Case sensitivity: openCypher property names are case-sensitive — p.Name and p.name are different.
Load before querying: Ensure await kgLayer.load() before accessing sublayers or metadata.
Link chart records: Both entities and relationships must be added as records for links to display.
knowledgegraph-query — Querying knowledge graphs with openCypherknowledgegraph-knowledgegraphlayer — Using KnowledgeGraphLayerknowledgegraph-search — Full-text searchknowledgegraph-applyedits — Editing graph entitiesknowledgegraph-datamodelediting — Data model editinglinkchart — Link chart visualizationarcgis-layers — Layer configuration and managementarcgis-interaction — Hit testing and event handlingarcgis-editing — Feature editing patternsdevelopment
Build map user interfaces with ArcGIS widgets, Map Components, and Calcite Design System. Use for adding legends, layer lists, search, tables, time sliders, and custom UI layouts.
development
Add specialized widgets including BuildingExplorer, FloorFilter, Track, Locate, HistogramRangeSlider, ScaleBar, Compass, NavigationToggle, and media viewers. Use for building exploration, indoor mapping, GPS tracking, and data histograms.
data-ai
Style and render geographic data with renderers, symbols, and visual variables. Use for creating thematic maps, heatmaps, class breaks, unique values, labels, and 3D visualization.
tools
Work with ArcGIS Utility Networks for modeling and analyzing connected infrastructure including network tracing, associations visualization, and topology validation. Use for electric, gas, water, and telecom network analysis.