Back to list
SaschaBrunnerCH

arcgis-knowledge-graphs

by SaschaBrunnerCH

Install AI assistant context files for ArcGIS Maps SDK for JavaScript development. Supports Claude skills and GitHub Copilot instructions.

1🍴 0📅 Jan 9, 2026

SKILL.md


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
  `
});
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);
});
<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>
// 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);
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

  1. Authentication required: Knowledge graph services typically require authentication

  2. Streaming for large results: Use executeQueryStreaming for queries that may return many results

  3. Geometry conversion: Convert geometries to WGS84 before using in spatial queries

  4. Case sensitivity: openCypher property names are case-sensitive

Score

Total Score

70/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon