# Query Knowledge Graph

## Observable: Query Knowledge Graph

### User Intent

"I want to explore entity relationships and visualize my knowledge graph"

### Operation

* **SDK Method**: `graphlit.queryContentsGraph()`
* **GraphQL**: `queryContentsGraph` query
* **Entity Type**: Content/Observable (graph relationships)
* **Common Use Cases**: Visualize knowledge graphs, explore entity relationships, discover connections, graph analytics

### TypeScript (Canonical)

```typescript
import { Graphlit } from 'graphlit-client';
import { ObservableTypes } from 'graphlit-client/dist/generated/graphql-types';

const graphlit = new Graphlit();

// Query knowledge graph for specific content
const graphResponse = await graphlit.queryContentsGraph({
  contents: [{ id: contentId }]
});

console.log('Knowledge Graph:');
console.log(`Nodes: ${graphResponse.graph.nodes?.length || 0}`);
console.log(`Edges: ${graphResponse.graph.edges?.length || 0}`);

// Access nodes (entities)
graphResponse.graph.nodes?.forEach(node => {
  console.log(`\n${node.type}: ${node.name}`);
  if (node.description) {
    console.log(`  Description: ${node.description}`);
  }
});

// Access edges (relationships)
graphResponse.graph.edges?.forEach(edge => {
  const from = graphResponse.graph.nodes?.find(n => n.id === edge.from);
  const to = graphResponse.graph.nodes?.find(n => n.id === edge.to);
  console.log(`${from?.name} → ${edge.type} → ${to?.name}`);
});

// Query graph across all content
const fullGraph = await graphlit.queryContentsGraph();

console.log(`\nFull knowledge graph:`);
console.log(`Total entities: ${fullGraph.graph.nodes?.length || 0}`);
console.log(`Total relationships: ${fullGraph.graph.edges?.length || 0}`);
```

## Query knowledge graph (snake\_case)

graph\_response = await graphlit.queryContentsGraph( filter=ContentFilterInput( contents=\[EntityReferenceFilterInput(id=content\_id)] ) )

print(f"Nodes: {len(graph\_response.graph.nodes or \[])}") print(f"Edges: {len(graph\_response.graph.edges or \[])}")

## Access nodes

for node in (graph\_response.graph.nodes or \[]): print(f"{node.type}: {node.name}")

## Access edges

for edge in (graph\_response.graph.edges or \[]): print(f"Relationship: {edge.from\_name} → {edge.type} → {edge.to\_name}")

````

**C#**:
```csharp
using Graphlit;

var client = new Graphlit();

// Query knowledge graph (PascalCase)
var graphResponse = await graphlit.QueryContentsGraph(new ContentFilter {
    Contents = new[] { new EntityReferenceFilter { Id = contentId } }
});

Console.WriteLine($"Nodes: {graphResponse.Graph.Nodes?.Count ?? 0}");
Console.WriteLine($"Edges: {graphResponse.Graph.Edges?.Count ?? 0}");

// Access nodes
foreach (var node in graphResponse.Graph.Nodes ?? new List<Node>())
{
    Console.WriteLine($"{node.Type}: {node.Name}");
}

// Access edges
foreach (var edge in graphResponse.Graph.Edges ?? new List<Edge>())
{
    Console.WriteLine($"{edge.From} → {edge.Type} → {edge.To}");
}
````

### Parameters

#### ContentFilter (Optional)

* **`contents`** (EntityReferenceFilter\[]): Filter by specific content
  * Query graph for specific documents
* **`collections`** (EntityReferenceFilter\[]): Filter by collection
* **`observableTypes`** (ObservableTypes\[]): Filter by entity types
  * `PERSON`, `ORGANIZATION`, `PLACE`, etc.

### Response

```typescript
{
  graph: {
    nodes: GraphNode[];  // Entities
    edges: GraphEdge[];  // Relationships
  }
}

interface GraphNode {
  id: string;              // Entity ID
  name: string;            // Entity name
  type: ObservableType;    // Entity type
  description?: string;    // Entity description
}

interface GraphEdge {
  from: string;            // Source entity ID
  to: string;              // Target entity ID
  type: string;            // Relationship type
  weight?: number;         // Relationship strength
}
```

### Developer Hints

#### Graph Must Be Built First

**Important**: Knowledge graph requires content with extraction workflow.

```typescript
// 1. Create extraction workflow
const workflow = await graphlit.createWorkflow({
  name: 'Entity Extraction',
  extraction: {
    jobs: [{
      connector: {
        type: EntityExtractionServiceTypes.ModelText,
        modelText: {
          specification: { id: extractionSpecId }
        }
      }
    }]
  }
});

// 2. Ingest with extraction
await graphlit.ingestUri(
  uri, undefined, undefined, undefined, true,
  { id: workflow.createWorkflow.id }
);

// 3. Now query graph
const graph = await graphlit.queryContentsGraph();
```

#### Filter by Content

```typescript
// Graph for specific document
const docGraph = await graphlit.queryContentsGraph({
  contents: [{ id: contentId }]
});

// Graph for collection
const collectionGraph = await graphlit.queryContentsGraph({
  collections: [{ id: collectionId }]
});

// Entire knowledge graph
const fullGraph = await graphlit.queryContentsGraph();
```

#### Analyze Relationships

```typescript
const graph = await graphlit.queryContentsGraph();

// Find most connected entities
const connectionCount = new Map<string, number>();

graph.graph.edges?.forEach(edge => {
  connectionCount.set(edge.from, (connectionCount.get(edge.from) || 0) + 1);
  connectionCount.set(edge.to, (connectionCount.get(edge.to) || 0) + 1);
});

// Sort by connections
const sorted = Array.from(connectionCount.entries())
  .sort((a, b) => b[1] - a[1])
  .slice(0, 10);

console.log('Top 10 most connected entities:');
sorted.forEach(([nodeId, count]) => {
  const node = graph.graph.nodes?.find(n => n.id === nodeId);
  console.log(`${node?.name}: ${count} connections`);
});
```

#### Visualize Graph

```typescript
// Export to visualization format (e.g., vis.js, d3.js)
function exportGraphForVisualization(graph: any) {
  const nodes = graph.graph.nodes?.map(node => ({
    id: node.id,
    label: node.name,
    title: node.description,
    group: node.type
  }));
  
  const edges = graph.graph.edges?.map(edge => ({
    from: edge.from,
    to: edge.to,
    label: edge.type,
    value: edge.weight
  }));
  
  return { nodes, edges };
}

const graph = await graphlit.queryContentsGraph();
const vizData = exportGraphForVisualization(graph);

// Use with visualization library
console.log(JSON.stringify(vizData, null, 2));
```

### Variations

#### 1. Query Full Knowledge Graph

Get entire graph:

```typescript
const graph = await graphlit.queryContentsGraph();

console.log(`Knowledge Graph:`);
console.log(`- Entities: ${graph.graph.nodes?.length || 0}`);
console.log(`- Relationships: ${graph.graph.edges?.length || 0}`);
```

#### 2. Graph for Specific Document

Single document graph:

```typescript
const docGraph = await graphlit.queryContentsGraph({
  contents: [{ id: contentId }]
});

console.log(`Document entities: ${docGraph.graph.nodes?.length || 0}`);
```

#### 3. Graph by Entity Type

Filter by entity types:

```typescript
const peopleGraph = await graphlit.queryContentsGraph({
  observableTypes: [
    ObservableTypes.Person,
    ObservableTypes.Organization
  ]
});

console.log('People and Organizations network');
```

#### 4. Collection Knowledge Graph

Graph for collection:

```typescript
const collectionGraph = await graphlit.queryContentsGraph({
  collections: [{ id: collectionId }]
});

console.log(`Collection graph:`);
console.log(`- Entities: ${collectionGraph.graph.nodes?.length || 0}`);
console.log(`- Relationships: ${collectionGraph.graph.edges?.length || 0}`);
```

#### 5. Find Entity Connections

Explore specific entity relationships:

```typescript
const graph = await graphlit.queryContentsGraph();

// Find entity by name
const targetEntity = graph.graph.nodes?.find(
  n => n.name.includes('Microsoft')
);

if (targetEntity) {
  // Find all connections
  const connections = graph.graph.edges?.filter(
    e => e.from === targetEntity.id || e.to === targetEntity.id
  );
  
  console.log(`${targetEntity.name} has ${connections?.length || 0} connections`);
  
  connections?.forEach(edge => {
    const other = graph.graph.nodes?.find(
      n => n.id === (edge.from === targetEntity.id ? edge.to : edge.from)
    );
    console.log(`- ${edge.type}: ${other?.name}`);
  });
}
```

#### 6. Graph Analytics

Analyze graph structure:

```typescript
const graph = await graphlit.queryContentsGraph();

// Count by entity type
const typeCounts = graph.graph.nodes?.reduce((acc, node) => {
  acc[node.type] = (acc[node.type] || 0) + 1;
  return acc;
}, {} as Record<string, number>);

console.log('Entity Distribution:');
Object.entries(typeCounts || {}).forEach(([type, count]) => {
  console.log(`  ${type}: ${count}`);
});

// Relationship type distribution
const edgeTypes = graph.graph.edges?.reduce((acc, edge) => {
  acc[edge.type] = (acc[edge.type] || 0) + 1;
  return acc;
}, {} as Record<string, number>);

console.log('\nRelationship Types:');
Object.entries(edgeTypes || {}).forEach(([type, count]) => {
  console.log(`  ${type}: ${count}`);
});
```

### Common Issues

**Issue**: Empty graph returned\
**Solution**: Ensure content was ingested with extraction workflow. Check entities were actually extracted.

**Issue**: No relationships/edges\
**Solution**: Relationships are automatically inferred from co-occurrence and context. More content = more relationships.

**Issue**: Graph too large to visualize\
**Solution**: Filter by specific content or collections. Use entity type filters to reduce scope.

**Issue**: Missing expected entities\
**Solution**: Check extraction workflow configuration. Try better extraction model (Claude Sonnet 3.7).

### Production Example

**Knowledge graph visualization pipeline**:

```typescript
// 1. Query knowledge graph
const graph = await graphlit.queryContentsGraph({
  collections: [{ id: collectionId }]
});

console.log('=== KNOWLEDGE GRAPH ANALYSIS ===\n');

// 2. Analyze graph structure
const nodeCount = graph.graph.nodes?.length || 0;
const edgeCount = graph.graph.edges?.length || 0;

console.log(`Total Entities: ${nodeCount}`);
console.log(`Total Relationships: ${edgeCount}`);
console.log(`Average Connections: ${(edgeCount / nodeCount * 2).toFixed(2)}\n`);

// 3. Find central entities (most connected)
const connectionCount = new Map<string, number>();

graph.graph.edges?.forEach(edge => {
  connectionCount.set(edge.from, (connectionCount.get(edge.from) || 0) + 1);
  connectionCount.set(edge.to, (connectionCount.get(edge.to) || 0) + 1);
});

const topEntities = Array.from(connectionCount.entries())
  .sort((a, b) => b[1] - a[1])
  .slice(0, 10);

console.log('Top 10 Central Entities:');
topEntities.forEach(([nodeId, count]) => {
  const node = graph.graph.nodes?.find(n => n.id === nodeId);
  console.log(`  ${count} connections: ${node?.name} (${node?.type})`);
});

// 4. Export for visualization
const vizData = {
  nodes: graph.graph.nodes?.map(node => ({
    id: node.id,
    label: node.name,
    title: node.description || node.name,
    group: node.type,
    value: connectionCount.get(node.id) || 1
  })),
  edges: graph.graph.edges?.map(edge => ({
    from: edge.from,
    to: edge.to,
    label: edge.type,
    value: edge.weight || 1
  }))
};

// Save for visualization tool
console.log('\nGraph exported for visualization');
// Use with vis.js, d3.js, Cytoscape.js, etc.
```

**Entity relationship explorer**:

```typescript
// Find relationships for specific entity
async function exploreEntityRelationships(entityName: string) {
  const graph = await graphlit.queryContentsGraph();
  
  // Find entity
  const entity = graph.graph.nodes?.find(
    n => n.name.toLowerCase().includes(entityName.toLowerCase())
  );
  
  if (!entity) {
    console.log(`Entity "${entityName}" not found`);
    return;
  }
  
  console.log(`\n=== ${entity.name} (${entity.type}) ===`);
  if (entity.description) {
    console.log(`Description: ${entity.description}`);
  }
  
  // Find all relationships
  const outgoing = graph.graph.edges?.filter(e => e.from === entity.id) || [];
  const incoming = graph.graph.edges?.filter(e => e.to === entity.id) || [];
  
  console.log(`\nOutgoing Relationships (${outgoing.length}):`);
  outgoing.forEach(edge => {
    const target = graph.graph.nodes?.find(n => n.id === edge.to);
    console.log(`  ${edge.type} → ${target?.name} (${target?.type})`);
  });
  
  console.log(`\nIncoming Relationships (${incoming.length}):`);
  incoming.forEach(edge => {
    const source = graph.graph.nodes?.find(n => n.id === edge.from);
    console.log(`  ${source?.name} (${source?.type}) → ${edge.type}`);
  });
}

// Usage
await exploreEntityRelationships('Microsoft');
await exploreEntityRelationships('John Smith');
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.graphlit.dev/api-guides/use-cases/knowledge-graph/observable-query-graph.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
