[go: up one dir, main page]

Skip to content

Add ES DSL field implementation

What does this MR do and why?

Introduces Search::Elastic::Dsl::Field, a new DSL module for declaring Elasticsearch indexable fields inside DSL-based models.

This provides a declarative API for defining:

  • Flat and nested fields
  • Computed and enriched fields
  • Default, conditional, and versioned fields

Part of the Elasticsearch DSL powering Search::Elastic::Dsl::Models::<Model>.


Usage example

class Vulnerability
  include Search::Elastic::Dsl::Field

  # Simple field
  field :title, type: :keyword

  # Field with default
  field :status, type: :keyword, default: 'active'

  # Nested fields
  field :scanner, type: :object do
    field :id, type: :keyword
    field :vendor, type: :keyword
  end

  # Computed & enriched fields
  field :hash, type: :keyword, compute: ->(r) { Digest::SHA256.hexdigest(r.data) }
  field :project_name, type: :keyword, enrich: ->(ids) { Project.where(id: ids).pluck(:name) }

  # Conditional, versioned field
  field :flag, type: :boolean, version: 2, if: -> { Feature.enabled?(:vulnerability_flag) }
end

Each field(...) call defines and stores metadata (type, compute, enrich, version, etc.) in a class-level fields_registry used by the DSL Builders.


Implementation details

  • New file: ee/lib/search/elastic/dsl/field.rb

    • Adds the field DSL and nested-field support via NestedFieldContext
    • Uses a class-level fields_registry to store definitions
    • Reports definition errors to Gitlab::ErrorTracking
  • Specs: ee/spec/lib/search/elastic/dsl/field_spec.rb

    • Covers flat, nested, computed, enriched, versioned, and conditional fields
    • Tests nested registry structure and error handling

Architectural context

flowchart TD
    %% === BUILDERS LAYER ===
    subgraph BUILDERS["Search::Elastic::Dsl::Builders::*"]
        JB["JsonBuilder<br/>–––––––––––––––––––––––––––––––<br/>Builds Elasticsearch JSON documents for indexing.<br/>Applies field definitions, compute rules, and version filters."]
        MB["MappingBuilder<br/>–––––––––––––––––––––––––––––––<br/>Generates Elasticsearch mappings.<br/>Includes only fields active for the current schema version."]
        PB["ProxyBuilder<br/>–––––––––––––––––––––––––––––––<br/>Creates enriched runtime proxies combining raw records<br/>and preloaded enrichment data for indexing."]
        SB["SettingsBuilder<br/>–––––––––––––––––––––––––––––––<br/>Builds index settings including analyzers,<br/>tokenizers, and normalization filters."]
    end


    %% === CORE DSL LAYER ===
    subgraph CORE["Search::Elastic::Dsl::* (Core Modules)"]
        F["Field DSL<br/>–––––––––––––––––––––––––––––––<br/>Central definition of all fields:<br/>type, compute, preload, default, and conditions."]
        SV["SchemaVersions<br/>–––––––––––––––––––––––––––––––<br/>Defines available schema versions and<br/>resolves which one is currently active."]
        ST["Settings<br/>–––––––––––––––––––––––––––––––<br/>Defines reusable analyzer, filter,<br/>and tokenizer configuration for indices."]
    end


    %% === RELATIONSHIPS ===
    JB --> F
    JB --> SV
    MB --> F
    MB --> SV
    PB --> F
    SB --> ST


    %% === STYLING ===
    classDef builder fill:#e8f1ff,stroke:#3366cc,stroke-width:1px,color:#000;
    classDef core fill:#f2faff,stroke:#66b3ff,stroke-width:1px,color:#000;
    classDef title fill:none,stroke:none,font-weight:bold;

    class BUILDERS,JB,MB,PB,SB builder;
    class CORE,F,SV,ST core;

References


Screenshots or screen recordings

Before After

How to set up and validate locally


MR acceptance checklist

Edited by Ugo Nnanna Okeadu

Merge request reports

Loading