
Rules & personalisation
A generic "similar items" list becomes a recommendation for this user by blending signals: positive signals lift candidates, negative signals demote them, and rules filter the result after fusion. Scoring stays in the signals and the fuses — rules only ever drop candidates.
| Piece | Purpose |
|---|---|
AddSignal(name, …) |
Lift candidates — a positive source, scaled by Weight(...) |
AddNegativeSignal(name, …) |
Demote candidates — scored like a signal, then combined by FuseFinal(...) |
AddRule(name, r => r.Filter(…)) |
Drop candidates — a hard filter, never a score change |
Personalise: lift products the current user has bought before. A positive signal with a small weight nudges familiar brands up without dominating.
.AddSignal("PreviouslyPurchased", s => s
.Weight(0.3f)
.From(ctx => ctx.Graph.Query()
.StartAt(CurrentUser)
.Out(N.Order.Type, E.Placed)
.Out(N.Product.Type, E.Contains)))
Demote: push down items the user returned. A negative signal is scored exactly like a positive one, then subtracted from the positive score by FuseFinal (default Fusion.Subtract).
.AddNegativeSignal("Returned", s => s
.From(ctx => ctx.Graph.Query()
.StartAt(CurrentUser)
.Out(N.Return.Type, E.Returned)
.Out(N.Product.Type, E.Contains)))
// Optional: scale the score down by how strong the negative is, instead of a flat subtraction.
.FuseFinal(Fusion.Discount)
A negative signal only touches candidates a positive signal already surfaced — it demotes, it never introduces new items. With a subtractive final fuse it shows up as a negative entry in that item's score breakdown, so you can still see why it dropped.
Constrain: keep only the requested category — conditionally.
.AddRule("CategoryFilter", r =>
{
r.Enabled(!string.IsNullOrEmpty(input.Category)); // skip when no category asked
r.Filter((ctx, candidates) => ctx.Graph.Query()
.StartAt(candidates)
.IsRelatedTo(Node.GetUID(N.Category.Type, input.Category))
.AsUIDEnumerable());
})
r.Enabled(false) makes any rule conditional on a request parameter — one scenario, many behaviours.