Member Junction
    Preparing search index...

    Provides entity-level LIKE-based search using RunView + UserSearchString. Searches all entities where AllowUserSearchAPI=true, returning results with rank-based scores.

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    AppliesLaneExtraFilter: boolean = true

    Each lane's rendered ExtraFilter is applied in the RunView that reads its entity (see the base class).

    config: SearchProviderConfig = null

    Config from the SearchProvider metadata record, set during Initialize()

    ConsumesLaneKinds: readonly LaneKind[] = ...

    Reads the scope's entity lanes, each with its own ExtraFilter and UserSearchString (see BaseSearchProvider.ConsumesLaneKinds).

    ResultsAreRowsOfLabelledEntity: boolean = true

    Every hit is a row of the entity it names, read through RunView as the user (see the base class).

    SourceType: SearchSource = 'entity'

    Which search source this provider represents

    MaxConcurrentEntitySearches: number = ...

    Maximum number of per-entity RunViews this provider will have IN FLIGHT at once.

    Previously the fan-out was a flat Promise.all over every scoped entity, and that is the innermost of THREE nested unbounded layers: SearchEngine fans out per resolved scope, then per provider within each scope, then this fans out per entity. With ~150 entities carrying AllowUserSearchAPI and a couple of scopes, one keystroke in the omnibar could put several hundred LIKE '%term%' scans on the connection pool simultaneously.

    PerEntityTimeoutMS does NOT bound that: it bounds how long each query is waited on, not how many run. The abandoned query keeps executing in the database (mssql Requests are not cancelled here), so under overload the timeouts fire, every entity resolves to an empty list, and the user sees silently missing results while the server is still working through the pile.

    Public + static so a deployment can tune it at startup, or override the default at process start via MJ_SEARCH_MAX_CONCURRENT_ENTITIES. The default of 8 is deliberately conservative: the fused result set is capped at topK regardless, so a lower ceiling costs latency on pathological fan-outs and buys back the pool.

    import { EntitySearchProvider } from '@memberjunction/search-engine';
    EntitySearchProvider.MaxConcurrentEntitySearches = 16;
    OnIncompleteResults?: (report: EntitySearchIncompleteReport) => void

    Optional deployment hook, invoked once per Search call that could not read every entity it was asked to read.

    Exists because a per-entity timeout or query failure resolves to an EMPTY LIST, which is indistinguishable downstream from "this entity genuinely has no matches". Fusion then publishes a confident, complete-looking result set that is quietly missing whole entities. The provider cannot widen its own return type — BaseSearchProvider.Search fixes it at SearchResultItem[] — so the partial-ness is surfaced here instead, as a report the host can turn into a "showing partial results" signal.

    The report is a fresh object per call and is never retained, so installing this hook introduces no shared mutable state between concurrent searches.

    Not invoked when every entity answered.

    PerEntityFetchDepth: number = ...

    How many rows to fetch PER ENTITY as the relevance-ranking candidate pool. This is DELIBERATELY decoupled from the global topK budget (bug C3): previously the per-entity limit was topK / entityCount floored at 3, so with ~150 searchable entities each entity returned only ~3 arbitrary rows and real matches beyond row 3 were never fetched — and enabling MORE entities starved each one further. Now each entity contributes up to this many candidates; the engine still trims the fused, relevance-sorted result set back to topK, so the returned count is unchanged — we only widen the candidate pool per entity. Public + static so a deployment can tune it at startup (larger entity counts may lower it to bound the row-materialization cost of the parallel fan-out), or override the default at process start via the MJ_SEARCH_PER_ENTITY_FETCH_DEPTH environment variable.

    PerEntityTimeoutMS: number = ...

    Per-entity hard timeout, in milliseconds. If one entity's RunView takes longer than this, we drop its results rather than hold the entire fan-out hostage. The query keeps running in SQL Server until completion (we can't cancel mssql Requests here), but the other entities' results still land for the user.

    Public + static so a deployment can tune it at startup — mirroring PerEntityFetchDepth. The 3s default keeps interactive/omnibar fan-outs responsive by dropping a pathological entity promptly instead of stalling the whole fan-out; deployments doing large unindexed LIKE scans can raise it, either by overriding the default at process start via the MJ_SEARCH_PER_ENTITY_TIMEOUT_MS environment variable or by assigning the static before serving:

    import { EntitySearchProvider } from '@memberjunction/search-engine';
    EntitySearchProvider.PerEntityTimeoutMS = 30_000;

    Accessors

    Methods

    • Run worker over items with at most limit calls in flight, preserving input order in the returned array.

      Static and internal-by-convention (not re-exported from the package index) so it can be exercised directly by the tests that pin the ceiling. next++ needs no lock: the increment is a single synchronous step and JavaScript gives us one of those at a time, so no two runners can claim the same index.

      Type Parameters

      • TIn
      • TOut

      Parameters

      • items: readonly TIn[]
      • limit: number
      • worker: (item: TIn, index: number) => Promise<TOut>

      Returns Promise<TOut[]>