Use Semantic Search
Why semantic search
Section titled “Why semantic search”Keyword search finds content that contains exact terms. Semantic search finds content that matches the meaning of a query, even when the exact words differ. A search for “how to reduce costs” can surface articles about “budget optimization” or “expense management” because Graph understands the semantic similarity.
This is particularly valuable for content-rich sites where users phrase their needs differently from the terminology authors used.
Step 1: Enable semantic search
Section titled “Step 1: Enable semantic search”Semantic search requires activation on your Graph subscription. It uses vector embeddings to represent content meaning, which requires additional processing during indexing.
Once enabled, Graph automatically generates vector embeddings for all indexed content during the next full sync. Incremental syncs generate embeddings for new and updated content.
Step 2: Query with semantic ranking
Section titled “Step 2: Query with semantic ranking”Use the SEMANTIC ranking mode to rank results by meaning similarity instead of keyword frequency.
query SemanticSearch {
ArticlePage(
where: {
_fulltext: { contains: "how to reduce operational costs" }
}
orderBy: { _ranking: SEMANTIC }
limit: 10
) {
items {
Headline
Summary
_score
_metadata {
url { default }
}
}
total
}
} The _score field reflects semantic similarity — higher values indicate closer meaning alignment with the query.
Step 3: Combine semantic with keyword search
Section titled “Step 3: Combine semantic with keyword search”For the best results, combine semantic understanding with keyword precision. Graph supports a hybrid approach that uses both scoring methods.
query HybridSearch($query: String!) {
ArticlePage(
where: {
_fulltext: {
contains: $query
match: SEMANTIC_AND_KEYWORD
}
}
orderBy: { _ranking: RELEVANCE }
limit: 10
) {
items {
Headline
Summary
_score
}
total
}
} Hybrid search ranks results using a weighted combination of keyword relevance and semantic similarity. Content that matches both dimensions ranks highest.
Step 4: Scope semantic search to specific fields
Section titled “Step 4: Scope semantic search to specific fields”By default, semantic search considers all full-text indexed fields. You can focus the semantic analysis on specific fields for more precise results.
query ScopedSemanticSearch {
ArticlePage(
where: {
_fulltext: {
contains: "machine learning applications"
boost: {
Headline: 3
Summary: 2
ArticleBody: 1
}
}
}
orderBy: { _ranking: SEMANTIC }
limit: 10
) {
items {
Headline
Summary
_score
}
}
} Step 5: Use semantic search with filters
Section titled “Step 5: Use semantic search with filters”Semantic search combines with all standard Graph filters. Apply filters first to narrow the candidate set, then rank semantically within that set.
query FilteredSemanticSearch($query: String!, $category: String!) {
ArticlePage(
where: {
_fulltext: { contains: $query }
Category: { eq: $category }
_metadata: {
published: { gte: "2025-01-01T00:00:00Z" }
status: { eq: "Published" }
}
}
orderBy: { _ranking: SEMANTIC }
limit: 10
) {
items {
Headline
Category
_score
_metadata { published }
}
total
facets {
Category { name count }
}
}
} Step 6: Implement a frontend semantic search UI
Section titled “Step 6: Implement a frontend semantic search UI”Integrate semantic search into a React component that provides a natural-language search experience.
import { useState, useCallback } from 'react';
import debounce from 'lodash/debounce';
export function SemanticSearch() {
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
const search = useCallback(
debounce(async (query) => {
if (!query || query.length < 3) return;
setLoading(true);
const response = await fetch(GRAPH_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${SINGLE_KEY}`,
},
body: JSON.stringify({
query: SEMANTIC_QUERY,
variables: { query },
}),
});
const { data } = await response.json();
setResults(data.ArticlePage.items);
setLoading(false);
}, 300),
[]
);
return (
<div>
<input
type="search"
placeholder="Ask a question..."
onChange={(e) => search(e.target.value)}
/>
{results.map((item) => (
<article key={item._metadata.url.default}>
<h3>{item.Headline}</h3>
<p>{item.Summary}</p>
<span>Relevance: {Math.round(item._score * 100)}%</span>
</article>
))}
</div>
);
} Performance considerations
Section titled “Performance considerations”- Embedding generation — Semantic indexing adds time to content sync. Expect slightly longer sync durations compared to keyword-only indexing.
- Query latency — Semantic queries take marginally longer than keyword queries due to vector similarity computation. Typical overhead is 50-100ms.
- Cost — Semantic search uses additional compute resources. Monitor usage through the Optimizely portal.