Curiosity

Technical Support: Search Use Cases

Five concrete search experiences taken from the sample app — recency lists, graph-scoped search, similar-case retrieval, hybrid search, and permission-aware search. Each one shows the C# you'd write, the rows you should see, and (for the visual workflows) where the screenshots go.

Sample dataset

Before you can validate any of this, your workspace needs a handful of rows. The technical-support seed ships with the following:

Type Count Notes
Manufacturer 4 "Acme", "Apple", "Dell", "Generic"
Device 12 One device per common laptop/phone model
Part 42 A handful of parts per device
Status 3 "Open", "Pending", "Resolved"
SupportCase 250 Mixed across devices and statuses
SupportCaseMessage 1,800 3–10 messages per case

Two example rows you'll see results referring to:

SupportCase  CS-0142
  ForDevice  MacBook Pro 14" (M3)
  HasStatus  Open
  Summary    "Screen flickers after waking from sleep"
  Time       2026-04-12T09:21:00Z

SupportCase  CS-0091
  ForDevice  Dell XPS 13 (2024)
  HasStatus  Resolved
  Summary    "Battery drains overnight even when lid is closed"
  Time       2026-02-03T18:04:00Z

The use cases below reference these so you can sanity-check ranking against a known answer.

Use case 1: find the most recent cases

The default "recent items" experience. Type-scope to SupportCase, sort newest first, cap at 10.

return Q().StartAt(nameof(Schema.Nodes.SupportCase))
          .SortByTimestamp(oldestFirst: false)
          .Take(10)
          .Emit("N");

Expected results (top 3): CS-0142, CS-0141, CS-0140 — purely time-ordered, no relevance signal.

Recent cases

Use case 2: search within a graph context

"Search for cases, but only within Apple's manufacturer scope" — the canonical example of graph-constrained search.

var request = SearchRequest.For("screen issue");
request.BeforeTypesFacet = new HashSet<string> { nameof(Schema.Nodes.SupportCase) };
request.TargetUIDs       = Q().StartAt(nameof(Schema.Nodes.Manufacturer), "Apple")
                              .Out(Edges.Makes)        // -> Part
                              .Out(Edges.PartOf)       // -> Device
                              .In (Edges.ForDevice)    // -> SupportCase
                              .AsUIDEnumerable()
                              .ToArray();

var query = await Graph.CreateSearchAsync(request);
return query.Emit();

Expected top hit on the sample dataset: CS-0142 ("Screen flickers...") on the MacBook Pro 14". A Dell case with the same text would be excluded by TargetUIDs.

TargetUIDs is an allow list. Empty means "search everything"; non-empty means "intersect with this set". For large allow lists, pre-compute the UIDs in a scheduled task and cache them as a node property.

"Find cases similar to this description, even if the wording differs."

return Q().StartAtSimilarText(
              text:      "laptop overheating after gaming",
              nodeTypes: new[] { nameof(Schema.Nodes.SupportCase) })
          .Take(5)
          .EmitWithScores();

Expected results — none of the rows contain the literal word "overheating", but the top three are about thermal issues:

Rank Case Score Why it matches
1 CS-0188 0.83 "Fans spin up loudly under load"
2 CS-0214 0.79 "Chassis becomes hot to touch during meetings"
3 CS-0102 0.74 "Performance throttles during video calls"
Similar cases

Combine BM25 + embeddings so exact-keyword hits still rank well alongside semantic neighbors.

var request = SearchRequest.For("battery drain MacBook");
request.BeforeTypesFacet = new HashSet<string> { nameof(Schema.Nodes.SupportCase) };
request.HybridSearch     = true;

var query = await Graph.CreateSearchAsync(request);
return query.Emit();

Expected: CS-0091 (Dell battery case) ranks below the MacBook cases here, even though it has the strongest keyword match on "battery drain", because the hybrid score also weights the MacBook context.

Same query, run as a specific user — results are filtered by ACL.

var request = SearchRequest.For("screen issue");
request.BeforeTypesFacet = new HashSet<string> { nameof(Schema.Nodes.SupportCase) };

var query = await Graph.CreateSearchAsUserAsync(request, CurrentUser);
return query.Emit();

If the connector restricted CS-0142 to the "Tier-2 Support" team, only members of that team see it in results. Everyone else gets the case omitted (not a "permission denied" — just gone from the list).

See Permission-aware search for the ingestion-side half.

Screenshot placeholders

These pages should pick up real screenshots once the demo app is deployed locally. Capture with snapframe against the local workspace:

dotnet serve <path-to-html-folder> --port 5000 &
PAGE_ID=$(snapframe navigate http://localhost:8080/search?q=screen+issue)
snapframe capture "$PAGE_ID" workspace/assets/tutorials/technical-support-search-context.png
snapframe stop

Files to refresh:

  • workspace/assets/tutorials/technical-support-recent-cases.png
  • workspace/assets/tutorials/technical-support-similar-cases.png
  • workspace/assets/tutorials/technical-support-search-context.png
  • workspace/assets/tutorials/technical-support-hybrid-search.png
© 2026 Curiosity. All rights reserved.
Powered by Neko