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.
86
82%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
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 locconst 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 patternsd84407b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.