# Filtered Search

> USearch for Mojo

A `predicate` in the `DenseSearchConfig` admits only the keys it approves, while non-matching entries still route the traversal, so recall does not collapse at low selectivity.
`PredicateArguments.of` compiles a Mojo function into the handler, judging a batch of keys per call against a state it reads through a pointer; a `usearch_predicate_callback_t` compiled in C installs unchanged through the same struct.

```mojo
def admits_tenant(keys: Span[Key, ImmUntrackedOrigin], admissions: Span[Admission, MutUntrackedOrigin], tenant: UInt64):
    for position in range(len(keys)):
        var owned = keys[position].as_integer().value() >> 32 == tenant
        admissions[position] = Admission.ADMIT if owned else Admission.REJECT

var predicate = PredicateArguments.of[admits_tenant](tenant_slot)
var admitted = index.search(queries, 10, arena, DenseSearchConfig(predicate=predicate))
```

The predicate runs on the executor's threads together, so it must be safe for concurrent use.
A `progress` knob on the configs of the long verbs hears how far a call has come, and a handler installed by `ProgressArguments.of` stops it by answering `Continuation.CANCEL`.
An insertion's handler reports but never cancels, so an `insert` batch stays all-or-nothing: every fallible step runs before the first entry is claimed, and a rejected batch publishes no entry.
Mojo handlers work on linux-64 in Mojo 1.2; AArch64 and macOS are confirmed by CI.

`from usearch import Admission`

## Admission

Whether a filtered search reports one candidate key or passes over it - `usearch_admission_t`.

```mojo
struct Admission
```

- `REJECT` = `Admission(Int32(0))`: Skip the key; the walk still routes through it.
- `ADMIT` = `Admission(Int32(1))`: Report the key among the matches.
- `code` `c_int`: The raw `usearch_admission_t` value the ABI exchanges.

Conforms to: `Copyable`, `Deinitable`, `Equatable`, `ImplicitlyCopyable`, `Movable`, `RegisterPassable`, `TrivialRegisterPassable`

