Member Junction
    Preparing search index...

    Abstract base class for search providers. Subclasses must be registered with @RegisterClass(BaseSearchProvider, 'DriverClassName') to be discoverable by the SearchEngine.

    Lifecycle:

    1. SearchEngine loads active SearchProvider records from the database
    2. For each record, ClassFactory creates an instance using DriverClass
    3. Initialize() is called with the provider's config from the DB record
    4. CheckAvailability() is called to verify the provider is operational
    5. If IsAvailable(), the provider participates in searches

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    AppliesLaneExtraFilter: boolean = false

    Whether this provider applies each entity lane's rendered ExtraFilter itself, in the RunView that reads the entity — so the engine need not re-check its hits against that lane bound. Only EntitySearchProvider sets it. Every other provider's hits for an entity with a lane ExtraFilter are re-checked by the engine, as the user, with PK IN (...) AND (<ExtraFilter>).

    Like ResultsAreRowsOfLabelledEntity, it is read from the provider the engine stamped on the result (ProviderId), never from a label, and never covers a promoted content-item hit (the filter was applied to the content item, not to the origin record it now names). A subclass inherits it; a subclass that changes Search so the lane ExtraFilter is no longer applied must override it to false.

    config: SearchProviderConfig = null

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

    ConsumesLaneKinds: readonly LaneKind[] = ...

    Reads the scope's Elasticsearch external-index rows (see BaseSearchProvider.ConsumesLaneKinds).

    ResultsAreRowsOfLabelledEntity: boolean = false

    Whether every result this provider returns is a row of the MJ entity its EntityName names, with RecordID that row's primary key, read from that entity through RunView as the searching user — so the entity's permissions and the user's row filters were applied when the row was read.

    The engine's permission pass trusts such results without re-reading them when no row filter applies (the hot path of the entity and full-text lanes). It verifies every other result with one PK IN (...) read per labelled entity, because a vector or external-index hit's EntityName is whatever the index says (an index or collection name, a metadata key) and its RecordID is the document's own id.

    Trust follows the provider instance the engine stamped on the result (SearchResultItem.ProviderId), never the SourceType a provider declares or stamps: SearchSource is a closed union, so any provider can call itself 'entity' or 'fulltext'. EntitySearchProvider and FullTextSearchProvider set this. Leave it false (the default) unless your hits really come out of RunView against the labelled entity; set on any other provider, it lets whoever writes the index choose which entity's permissions apply. It never covers a hit the engine promoted from MJ: Content Items to its origin record (SearchResultItem.PromotedFromContentItemID): the provider never read that row.

    A subclass inherits this flag. A subclass that changes Search so its hits no longer come out of RunView against the labelled entity must override it to false.

    SourceType: SearchSource = 'fulltext'

    Which search source this provider represents

    Accessors

    Methods

    • Execute a search and return result items with scores.

      When scopeConstraints is provided, the provider MUST:

      1. Narrow its retrieval surface to match the constraint (e.g., VectorSearchProvider queries only the listed ExternalIndexes with matching IndexType, EntitySearchProvider queries only the listed Entities, StorageSearchProvider queries only the listed accounts/folders, 3rd-party providers filter by their own IndexType).
      2. Apply any rendered MetadataFilter / ExtraFilter / UserSearchString / FolderPath values as native filters.
      3. Implement permission push-down (see Section 3.6 of plans/search-scopes-rag-plus.md) — never surface results the contextUser cannot see.
      4. Honor scopeConstraints.QueryTransforms when a per-provider rewrite is supplied — look up by your SourceType or provider-specific key and use that string in place of the raw query.

      When scopeConstraints is undefined, the provider runs unconstrained (backward compatible pre-scope behavior). Inside scopeConstraints, a lane list that is undefined means unscoped too, but a DEFINED, EMPTY list means the scope gives this provider nothing: return no results without querying — never fall back to "everything" or to a default index (see the field docs on ScopeConstraints). The engine does not call a provider whose ConsumesLaneKinds are all empty in a scope, but a provider reading several lane kinds still receives [] for the ones a scope leaves empty.

      Parameters

      • query: string

        The search query text

      • topK: number

        Maximum number of results to retrieve

      • _filters: SearchFilters

        Optional filters to narrow results

      • _contextUser: UserInfo

        The user performing the search

      • OptionalscopeConstraints: ScopeConstraints

        Optional per-scope constraint set, pre-rendered with SearchContext values

      Returns Promise<SearchResultItem[]>

      Scored result items from this provider