Curiosity
Illustration of graph-as-filter showing a network graph with highlighted nodes and a constrained candidate set.

Using the graph

Embedding similarity alone returns the most similar items across the entire corpus. The graph lets you scope that — either as a hard filter or as a soft ranking signal.


The graph as a filter — search within a product's ticket history:

// Get all tickets for a specific product.
var scope = Q().StartAt("Product", "MBA-2024")
               .In("ForProduct")
               .AsUIDEnumerable()
               .ToArray();

var similar = await Q()
    .StartAt(seedTicketUID)
    .ToSimilarity()
    .AddSignal("embedding", s => s.FromAsync(async ctx =>
        (await ctx.Graph.Query().StartAtSimilarTextAsync(bodyText, 20, new[] { N.Ticket.Type }))
        .AsUIDEnumerable()))
    .AddRule("product-filter", r => r.Filter((ctx, candidates) =>
        candidates.Where(uid => scope.Contains(uid))))
    .ExecuteAsync(ct);

Without the filter, "similar tickets" might return results from unrelated products. The graph constraint scopes similarity to what's relevant — without a separate index per product. It composes with permissions too: scope can be constrained to UIDs the current user can see.


The graph as a ranking signal — boost items that are graph-neighbours of the seed. Items that are both semantically similar and closely connected rank higher.

Side-by-side comparison of ranked lists with and without graph boost, featuring a graph snippet.
var sharedTags = Q().StartAt(seedUID).Out("HasTag").AsUIDEnumerable().ToArray();

var results = await Graph.Query()
    .StartAt(seedUID)
    .ToSimilarity()
    .AddSignal("embedding", s => s
        .Weight(0.7f)
        .FromAsync(async ctx =>
            (await ctx.Graph.Query().StartAtSimilarTextAsync(bodyText, 20, new[] { N.Ticket.Type }))
            .AsUIDEnumerable()))
    .AddSignal("shared-tags", s => s
        .Weight(0.3f)
        .From(ctx => ctx.Graph.Query().StartAt(sharedTags).In("HasTag").Distinct().AsUIDEnumerable()))
    .Fuse(f => f.UsingReciprocalRankFusion())
    .ExecuteAsync(ct);

Filter when a constraint is hard ("only this product"); use a weighted signal when it's a preference ("prefer the same project, but don't exclude others").

Similarity engine