Advanced14 min read

Knowledge Graph Query Patterns and Relationships

Advanced knowledge graph querying. Learn complex relationship queries, graph traversal patterns, entity co-occurrence, and guided search strategies.

Once you've built a knowledge graph, querying it effectively unlocks powerful insights—finding relationships, co-occurrences, and patterns across your content. This guide covers advanced query patterns beyond basic entity extraction.

What You'll Learn

  • Relationship queries (who works where)
  • Entity co-occurrence analysis
  • Graph traversal patterns
  • Temporal entity queries
  • Guided search with entities
  • Building recommendation engines

Part 1: Relationship Queries

Find Person-Organization Relationships

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

const graphlit = new Graphlit();

// Get all people
const people = await graphlit.queryObservables({
  filter: {
    types: [ObservableTypes.Person]
  }
});

// For each person, find related organizations
const relationships = [];

for (const personResult of people.observables?.results || []) {
  const person = personResult.observable;
  
  // Get content mentioning this person
  const personContent = await graphlit.queryContents({
    filter: {
      observations: {
        observables: [{ id: person.id }]
      }
    }
  });
  
  // Extract organizations from same content
  for (const content of personContent.contents.results) {
    const details = await graphlit.getContent(content.id);
    
    const orgs = details.content.observations
      ?.filter(obs => obs.type === ObservableTypes.Organization)
      .map(obs => obs.observable.name);
    
    orgs?.forEach(org => {
      relationships.push({
        person: person.name,
        organization: org
      });
    });
  }
}

// Display relationships
console.log('Person → Organization relationships:');
relationships.forEach(rel => {
  console.log(`  ${rel.person} ↔ ${rel.organization}`);
});

Example output:

Person → Organization relationships:
  Alice Johnson ↔ Acme Corp
  Alice Johnson ↔ OpenAI
  Bob Smith ↔ Acme Corp
  Carol Lee ↔ Google

Part 2: Entity Co-Occurrence

Find Entities Mentioned Together

// Get content
const content = await graphlit.getContent(contentId);

// Build co-occurrence matrix
interface CoOccurrence {
  entity1: string;
  entity2: string;
  pages: number[];
  strength: number;
}

const cooccurrences: CoOccurrence[] = [];

const observations = content.content.observations || [];

// For each pair of entities
for (let i = 0; i < observations.length; i++) {
  for (let j = i + 1; j < observations.length; j++) {
    const obs1 = observations[i];
    const obs2 = observations[j];
    
    // Get pages where each appears
    const pages1 = new Set(obs1.occurrences?.map(occ => occ.pageIndex));
    const pages2 = new Set(obs2.occurrences?.map(occ => occ.pageIndex));
    
    // Find shared pages
    const sharedPages = Array.from(pages1).filter(p => pages2.has(p));
    
    if (sharedPages.length > 0) {
      cooccurrences.push({
        entity1: obs1.observable.name,
        entity2: obs2.observable.name,
        pages: sharedPages,
        strength: sharedPages.length
      });
    }
  }
}

// Sort by strength
cooccurrences
  .sort((a, b) => b.strength - a.strength)
  .slice(0, 10)
  .forEach(co => {
    console.log(`${co.entity1} ↔ ${co.entity2} (${co.strength} pages)`);
  });

Use cases:

  • "Find people who work together" (co-mentioned)
  • "Find related products" (discussed together)
  • "Find connected topics" (appear in same docs)

Part 3: Temporal Entity Analysis

Track Entity Mentions Over Time

// Get entity
const entity = await graphlit.queryObservables({
  filter: {
    searchText: "Project Phoenix",
    types: [ObservableTypes.Product]
  }
});

const entityId = entity.observables?.results?.[0]?.observable.id;

// Get all content mentioning this entity
const mentions = await graphlit.queryContents({
  filter: {
    observations: {
      observables: [{ id: entityId }]
    }
  }
});

// Group by month
const timeline = new Map<string, number>();

mentions.contents.results.forEach(content => {
  const date = new Date(content.creationDate);
  const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
  timeline.set(monthKey, (timeline.get(monthKey) || 0) + 1);
});

// Display timeline
console.log('Mentions of "Project Phoenix" over time:');
Array.from(timeline.entries())
  .sort((a, b) => a[0].localeCompare(b[0]))
  .forEach(([month, count]) => {
    console.log(`  ${month}: ${count} mentions`);
  });

Example output:

Mentions of "Project Phoenix" over time:
  2024-01: 5 mentions
  2024-02: 12 mentions
  2024-03: 8 mentions
  2024-04: 15 mentions

Use cases:

  • Track project activity
  • Monitor competitor mentions
  • Identify trending topics

Part 4: Guided Search

Entity-Filtered Search

// Find Alice
const aliceEntity = await graphlit.queryObservables({
  filter: {
    searchText: "Alice Johnson",
    types: [ObservableTypes.Person]
  }
});

const aliceId = aliceEntity.observables?.results?.[0]?.observable.id;

// Search content mentioning Alice about "budget"
const results = await graphlit.queryContents({
  search: "budget allocation",
  filter: {
    observations: {
      observables: [{ id: aliceId }]
    }
  }
});

console.log(`Documents about "budget" mentioning Alice: ${results.contents.results.length}`);

Multi-Entity Filter

// Find content mentioning BOTH Alice AND Acme Corp
const acmeEntity = await graphlit.queryObservables({
  filter: {
    searchText: "Acme Corp",
    types: [ObservableTypes.Organization]
  }
});

const acmeId = acmeEntity.observables?.results?.[0]?.observable.id;

const multiFilter = await graphlit.queryContents({
  search: "partnership",
  filter: {
    observations: {
      observables: [
        { id: aliceId },
        { id: acmeId }
      ]
    }
  }
});

console.log('Documents about Alice AND Acme Corp:', multiFilter.contents.results.length);

Part 5: Building Recommendation Engines

Content Recommendation by Entities

// User reads document A
const docA = await graphlit.getContent(documentAId);

// Extract entities from doc A
const entitiesA = docA.content.observations
  ?.map(obs => obs.observable.id) || [];

// Find other docs with similar entities
const recommendations = await graphlit.queryContents({
  filter: {
    observations: {
      observables: entitiesA.slice(0, 5).map(id => ({ id }))  // Top 5 entities
    }
  },
  limit: 10
});

console.log('Recommended documents:');
recommendations.contents.results.forEach(doc => {
  console.log(`  - ${doc.name}`);
});

Use cases:

  • "More like this" features
  • Related articles
  • Cross-document discovery

Part 6: Network Analysis

Entity Influence Score

// Calculate "influence" based on co-mentions
async function calculateInfluence() {
  const people = await graphlit.queryObservables({
    filter: { types: [ObservableTypes.Person] }
  });
  
  const influence = new Map<string, number>();
  
  for (const personResult of people.observables?.results || []) {
    const person = personResult.observable;
    
    // Count mentions
    const mentionCount = person.observationCount || 0;
    
    // Count unique documents mentioning them
    const docs = await graphlit.queryContents({
      filter: {
        observations: {
          observables: [{ id: person.id }]
        }
      }
    });
    
    const uniqueDocs = docs.contents.results.length;
    
    // Influence = mentions * unique docs
    influence.set(person.name, mentionCount * uniqueDocs);
  }
  
  // Top influencers
  Array.from(influence.entries())
    .sort((a, b) => b[1] - a[1])
    .slice(0, 10)
    .forEach(([name, score]) => {
      console.log(`${name}: influence score ${score}`);
    });
}

Common Patterns

Pattern 1: Find Clusters

// Find people who work on same projects
const projectClusters = new Map<string, Set<string>>();

const projects = await graphlit.queryObservables({
  filter: { types: [ObservableTypes.Product] }
});

for (const project of projects.observables?.results || []) {
  const docs = await graphlit.queryContents({
    filter: {
      observations: {
        observables: [{ id: project.observable.id }]
      }
    }
  });
  
  const peopleInProject = new Set<string>();
  
  for (const doc of docs.contents.results) {
    const details = await graphlit.getContent(doc.id);
    
    details.content.observations
      ?.filter(obs => obs.type === ObservableTypes.Person)
      .forEach(person => {
        peopleInProject.add(person.observable.name);
      });
  }
  
  projectClusters.set(project.observable.name, peopleInProject);
}

// Display clusters
projectClusters.forEach((people, project) => {
  console.log(`${project}: ${Array.from(people).join(', ')}`);
});

Pattern 2: Expertise Mapping

// Map people to topics
const expertise = new Map<string, Set<string>>();

const people = await graphlit.queryObservables({
  filter: { types: [ObservableTypes.Person] }
});

for (const personResult of people.observables?.results || []) {
  const docs = await graphlit.queryContents({
    filter: {
      observations: {
        observables: [{ id: personResult.observable.id }]
      }
    }
  });
  
  const topics = new Set<string>();
  
  for (const doc of docs.contents.results) {
    const details = await graphlit.getContent(doc.id);
    
    // Extract product/topic entities
    details.content.observations
      ?.filter(obs => obs.type === ObservableTypes.Product)
      .forEach(topic => {
        topics.add(topic.observable.name);
      });
  }
  
  expertise.set(personResult.observable.name, topics);
}

// Display expertise
expertise.forEach((topics, person) => {
  console.log(`${person} is expert in: ${Array.from(topics).join(', ')}`);
});

What's Next?

You now understand advanced knowledge graph queries. Next steps:

  1. Build entity dashboards showing relationships
  2. Create recommendation engines based on entities
  3. Track entity evolution over time

Related guides:

Happy querying! 🔍

Ready to Build with Graphlit?

Start building AI-powered applications with our API-first platform. Free tier includes 100 credits/month — no credit card required.

No credit card required • 5 minutes to first API call

Knowledge Graph Query Patterns and Relationships | Graphlit Developer Guides