Search

Query, search, and filter your graph data with powerful engines.

Querying and Search

Three built-in engines for exploring your graph.

QueryEngine

Graph traversal and structural queries.

import { useInferaGraph } from '@inferagraph/core/react';

function PatriarchExplorer() {
  const { queryEngine } = useInferaGraph();

  const neighbors = queryEngine.getNeighbors('abraham', 2);
  const path = queryEngine.findPath('abraham', 'canaan');
  const sub = queryEngine.getSubgraph(['abraham', 'isaac', 'jacob']);

  return (
    <div>
      <h2>Abraham's Neighbors</h2>
      {neighbors.map(n => <li key={n.id}>{n.id}</li>)}
    </div>
  );
}

SearchEngine

Full-text search with relevance scoring.

import { useInferaGraph } from '@inferagraph/core/react';
import { useState } from 'react';

function BibleSearch() {
  const { searchEngine } = useInferaGraph();
  const [query, setQuery] = useState('');

  const results = searchEngine.search(query);

  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      {results.map(r => <li key={r.nodeId}>{r.nodeId} ({r.score})</li>)}
    </div>
  );
}

FilterEngine

Predicate-based node filtering.

import { useInferaGraph } from '@inferagraph/core/react';

function PatriarchFilter() {
  const { filterEngine } = useInferaGraph();

  // Find all people from the Patriarchs era
  const patriarchs = filterEngine.filter(
    (attrs) => attrs.type === 'person' && attrs.era === 'Patriarchs'
  );

  return (
    <ul>
      {patriarchs.map(p => <li key={p.id}>{p.id}</li>)}
    </ul>
  );
}

Semantic Search

Add an llm prop and useInferaGraphSearch() auto-detects search mode: short tokens hit the keyword index; sentence-length queries run vector search via embeddings. Same API, the right answer either way.

import { useInferaGraphSearch } from '@inferagraph/core/react';
import { useState } from 'react';

function SmartSearch() {
  const { search } = useInferaGraphSearch();
  const [results, setResults] = useState([]);

  async function go(q) {
    // Auto-detect:
    //  - 'abraham'                          → keyword
    //  - 'patriarchs who left their homeland' → semantic
    const hits = await search(q);
    setResults(hits);
  }
}

Embedding Storage

Embeddings can be stored at three tiers. Pick what matches your traffic and budget; the API is the same in all three cases.

  • No store — keyword-only search, zero embedding calls.
  • Cache as store — reuse a CacheProvider for embeddings. Easiest upgrade path.
  • Dedicated EmbeddingStore — implement the contract for any vector-native backend. inMemoryEmbeddingStore() ships built-in.
// Tier 1 — no semantic search (keyword only)
<InferaGraph data={data} llm={llm} />

// Tier 2 — bring-your-own-cache (cache as embedding store)
import { lruCache } from '@inferagraph/core/data';
<InferaGraph data={data} llm={llm} cache={lruCache()} />

// Tier 3 — dedicated EmbeddingStore (vector-native backend)
import { inMemoryEmbeddingStore } from '@inferagraph/core/data';
<InferaGraph
  data={data}
  llm={llm}
  embeddingStore={inMemoryEmbeddingStore()}
/>

// Every embedding is stamped with model + version + content hash.
// Unchanged content is never re-embedded.

Provenance: every stored embedding carries the model id, version, and a hash of the source content. When content or model changes, the embedding is regenerated; otherwise it's reused indefinitely. See Embeddings for the full contract and per-tier tradeoffs.