From 4eaef2cc8fff2b111c745b60c4c83c67545c3560 Mon Sep 17 00:00:00 2001 From: Alisa Frunza Date: Thu, 28 Aug 2025 21:58:56 +0200 Subject: [PATCH 1/3] Add missing documentation for the existing Advanced Search filters --- doc/development/advanced_search.md | 453 +++++++++++++++++++++++++++++ 1 file changed, 453 insertions(+) diff --git a/doc/development/advanced_search.md b/doc/development/advanced_search.md index c6fb7392749f12..2a69e738a58602 100644 --- a/doc/development/advanced_search.md +++ b/doc/development/advanced_search.md @@ -2239,6 +2239,459 @@ Requires `noteable_type` field. Query with `noteable_type` in options. Sets `_so } ``` +### `by_iids` + +Filters documents by multiple IID values. + +**Required fields:** `iid` +**Options:** `iids` - array of IID values to match + +```json +{ + "bool": { + "_name": "filters:iids", + "filter": { + "terms": { + "iid": [1, 2, 3] + } + } + } +} +``` + +### `by_closed_at` + +Filters by closed date range. + +**Required fields:** `closed_at` +**Options:** + +- `closed_after` - ISO date string for minimum closed date +- `closed_before` - ISO date string for maximum closed date + +```json +{ + "bool": { + "_name": "filters:closed_after", + "must": { + "range": { + "closed_at": { + "gte": "2025-01-01T00:00:00Z" + } + } + } + } +} +``` + +### `by_created_at` + +Filters by creation date range. + +**Required fields:** `created_at` +**Options:** + +- `created_after` - ISO date string for minimum creation date +- `created_before` - ISO date string for maximum creation date + +```json +{ + "bool": { + "_name": "filters:created_after", + "must": { + "range": { + "created_at": { + "gte": "2025-01-01T00:00:00Z" + } + } + } + } +} +``` + +### `by_updated_at` + +Filters by update date range. + +**Required fields:** `updated_at` +**Options:** + +- `updated_after` - ISO date string for minimum update date +- `updated_before` - ISO date string for maximum update date + +```json +{ + "bool": { + "_name": "filters:updated_after", + "must": { + "range": { + "updated_at": { + "gte": "2025-01-01T00:00:00Z" + } + } + } + } +} +``` + +### `by_due_date` + +Filters by due date range. + +**Required fields:** `due_date` +**Options:** + +- `due_after` - ISO date string for minimum due date +- `due_before` - ISO date string for maximum due date + +```json +{ + "bool": { + "_name": "filters:due_after", + "must": { + "range": { + "due_date": { + "gte": "2025-01-01T00:00:00Z" + } + } + } + } +} +``` + +### `by_milestone` + +Filters by milestone title or milestone presence. The milestone_title filters and wildcard filters are mutually exclusive. + +**Required fields:** `milestone_title` +**Options:** + +- `milestone_title` - array of milestone titles to include +- `not_milestone_title` - array of milestone titles to exclude +- `any_milestones` - boolean, filters for documents with any milestone +- `none_milestones` - boolean, filters for documents with no milestone + +Example with `milestone_title`: + +```json +{ + "bool": { + "must": { + "terms": { + "_name": "filters:milestone_title", + "milestone_title": ["18.1", "18.2"] + } + } + } +} +``` + +Example with `none_milestones`: + +```json +{ + "bool": { + "_name": "filters:none_milestones", + "must_not": { + "exists": { + "field": "milestone_title" + } + } + } +} +``` + +### `by_milestone_state` + +Filters by milestone state with temporal conditions. + +**Required fields:** `milestone_state`, `milestone_start_date`, `milestone_due_date` +**Options:** + +- `milestone_state_filters` - array containing one or more of: `:upcoming`, `:started`, `:not_upcoming`, `:not_started` + +Example for `:upcoming` filter: + +```json +{ + "bool": { + "_name": "filters:milestone_state_upcoming", + "must": [ + { + "term": { + "milestone_state": "active" + } + }, + { + "range": { + "milestone_start_date": { + "gt": "now/d" + } + } + } + ] + } +} +``` + +Example for `:started` filter: + +```json +{ + "bool": { + "_name": "filters:milestone_state_started", + "must": [ + { + "term": { + "milestone_state": "active" + } + }, + { + "bool": { + "should": [ + { + "range": { + "milestone_start_date": { + "lte": "now/d" + } + } + }, + { + "bool": { + "must_not": { + "exists": { + "field": "milestone_start_date" + } + } + } + } + ] + } + }, + { + "bool": { + "should": [ + { + "range": { + "milestone_due_date": { + "gte": "now/d" + } + } + }, + { + "bool": { + "must_not": { + "exists": { + "field": "milestone_due_date" + } + } + } + } + ] + } + } + ], + "must_not": { + "bool": { + "must": [ + { + "bool": { + "must_not": { + "exists": { + "field": "milestone_start_date" + } + } + } + }, + { + "bool": { + "must_not": { + "exists": { + "field": "milestone_due_date" + } + } + } + } + ] + } + } + } +} +``` + +### `by_assignees` + +Filters by assignee IDs with support for various matching modes. + +**Required fields:** `assignee_id` +**Options:** + +- `assignee_ids` - array of assignee IDs that must ALL be present +- `not_assignee_ids` - array of assignee IDs to exclude +- `or_assignee_ids` - array of assignee IDs where ANY can match +- `none_assignees` - boolean, filters for documents with no assignees +- `any_assignees` - boolean, filters for documents with any assignee + +Example with `assignee_ids` (ALL must match): + +```json +{ + "bool": { + "_name": "filters:assignee_ids", + "must": [ + { + "term": { + "assignee_id": 123 + } + }, + { + "term": { + "assignee_id": 456 + } + } + ] + } +} +``` + +Example with `or_assignee_ids` (ANY can match): + +```json +{ + "bool": { + "must": { + "terms": { + "_name": "filters:or_assignee_ids", + "assignee_id": [123, 456, 789] + } + } + } +} +``` + +Example with `none_assignees`: + +```json +{ + "bool": { + "_name": "filters:none_assignees", + "must_not": { + "exists": { + "field": "assignee_id" + } + } + } +} +``` + +### `by_weight` + +Filters by issue weight (integer value). + +**Required fields:** `weight` +**Options:** + +- `weight` - exact weight value to match (integer) +- `not_weight` - weight value to exclude (integer) +- `none_weight` - boolean, filters for documents with no weight +- `any_weight` - boolean, filters for documents with any weight + +```json +{ + "term": { + "weight": { + "_name": "filters:weight", + "value": 3 + } + } +} +``` + +### `by_health_status` + +Filters by health status field. + +**Required fields:** `health_status` +**Options:** + +- `health_status` - array of health status IDs to include +- `not_health_status` - array of health status IDs to exclude +- `none_health_status` - boolean, filters for documents with no health status +- `any_health_status` - boolean, filters for documents with any health status + +```json +{ + "bool": { + "must": { + "terms": { + "_name": "filters:health_status", + "health_status": [1, 2] + } + } + } +} +``` + +### `by_label_names` + +Filters by label names with support for various matching modes and scoped label wildcards. + +**Required fields:** `label_names` +**Options:** + +- `label_names` - array of label names that must ALL be present +- `not_label_names` - array of label names to exclude +- `or_label_names` - array of label names where ANY can match +- `none_label_names` - boolean, filters for documents with no labels +- `any_label_names` - boolean, filters for documents with any label + +Supports scoped label wildcards like `"workflow::*"` to match all labels starting with `"workflow::"`. + +Example with exact matches: + +```json +{ + "bool": { + "_name": "filters:label_names", + "must": [ + { + "term": { + "label_names": "advanced search" + } + }, + { + "term": { + "label_names": "GLQL" + } + } + ] + } +} +``` + +Example with scoped label wildcard: + +```json +{ + "bool": { + "_name": "filters:or_label_names", + "should": [ + { + "prefix": { + "label_names": "workflow::" + } + }, + { + "term": { + "label_names": "backend" + } + } + ], + "minimum_should_match": 1 + } +} +``` + ## Testing scopes Test any scope in the Rails console -- GitLab From 29a64f89249b76e40a5def87b63a1f61240393a2 Mon Sep 17 00:00:00 2001 From: Terri Chu Date: Tue, 2 Sep 2025 11:56:06 -0400 Subject: [PATCH 2/3] Apply suggestions from duo --- doc/development/advanced_search.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/development/advanced_search.md b/doc/development/advanced_search.md index 2a69e738a58602..508b12bf1ca9c7 100644 --- a/doc/development/advanced_search.md +++ b/doc/development/advanced_search.md @@ -2361,7 +2361,7 @@ Filters by due date range. ### `by_milestone` -Filters by milestone title or milestone presence. The milestone_title filters and wildcard filters are mutually exclusive. +Filters by milestone title or milestone presence. The milestone title filters (`milestone_title`, `not_milestone_title`) and milestone presence filters (`any_milestones`, `none_milestones`) are mutually exclusive. **Required fields:** `milestone_title` **Options:** @@ -2645,7 +2645,7 @@ Filters by label names with support for various matching modes and scoped label - `none_label_names` - boolean, filters for documents with no labels - `any_label_names` - boolean, filters for documents with any label -Supports scoped label wildcards like `"workflow::*"` to match all labels starting with `"workflow::"`. +Supports scoped label wildcards like `"workflow::*"` to match all labels starting with `"workflow::"`. The wildcard is converted to a prefix query in Elasticsearch. Example with exact matches: -- GitLab From b42bcd8c86c527449fc30a052c428621d6ab8fd3 Mon Sep 17 00:00:00 2001 From: Terri Chu Date: Tue, 2 Sep 2025 12:05:11 -0400 Subject: [PATCH 3/3] Small refactor for optional fields --- doc/development/advanced_search.md | 55 +++++++++++++----------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/doc/development/advanced_search.md b/doc/development/advanced_search.md index 508b12bf1ca9c7..a8cdeb1f2d3ac1 100644 --- a/doc/development/advanced_search.md +++ b/doc/development/advanced_search.md @@ -2243,8 +2243,9 @@ Requires `noteable_type` field. Query with `noteable_type` in options. Sets `_so Filters documents by multiple IID values. -**Required fields:** `iid` -**Options:** `iids` - array of IID values to match +**Required fields:** + +- `iids` - array of IID values to match ```json { @@ -2261,10 +2262,9 @@ Filters documents by multiple IID values. ### `by_closed_at` -Filters by closed date range. +Filters by closed date range. At least one optional field must be provided. -**Required fields:** `closed_at` -**Options:** +**Optional fields:** - `closed_after` - ISO date string for minimum closed date - `closed_before` - ISO date string for maximum closed date @@ -2286,10 +2286,9 @@ Filters by closed date range. ### `by_created_at` -Filters by creation date range. +Filters by creation date range. At least one optional field must be provided. -**Required fields:** `created_at` -**Options:** +**Optional fields:** - `created_after` - ISO date string for minimum creation date - `created_before` - ISO date string for maximum creation date @@ -2311,10 +2310,9 @@ Filters by creation date range. ### `by_updated_at` -Filters by update date range. +Filters by update date range. At least one optional field must be provided. -**Required fields:** `updated_at` -**Options:** +**Optional fields:** - `updated_after` - ISO date string for minimum update date - `updated_before` - ISO date string for maximum update date @@ -2336,10 +2334,9 @@ Filters by update date range. ### `by_due_date` -Filters by due date range. +Filters by due date range. At least one optional field must be provided. -**Required fields:** `due_date` -**Options:** +**Optional fields:** - `due_after` - ISO date string for minimum due date - `due_before` - ISO date string for maximum due date @@ -2361,10 +2358,11 @@ Filters by due date range. ### `by_milestone` -Filters by milestone title or milestone presence. The milestone title filters (`milestone_title`, `not_milestone_title`) and milestone presence filters (`any_milestones`, `none_milestones`) are mutually exclusive. +Filters by milestone title or milestone presence. At least one optional field must be provided. +The milestone title filters (`milestone_title`, `not_milestone_title`) and milestone presence +filters (`any_milestones`, `none_milestones`) are mutually exclusive. -**Required fields:** `milestone_title` -**Options:** +**Optional fields:** - `milestone_title` - array of milestone titles to include - `not_milestone_title` - array of milestone titles to exclude @@ -2405,8 +2403,7 @@ Example with `none_milestones`: Filters by milestone state with temporal conditions. -**Required fields:** `milestone_state`, `milestone_start_date`, `milestone_due_date` -**Options:** +**Required fields:** - `milestone_state_filters` - array containing one or more of: `:upcoming`, `:started`, `:not_upcoming`, `:not_started` @@ -2521,10 +2518,9 @@ Example for `:started` filter: ### `by_assignees` -Filters by assignee IDs with support for various matching modes. +Filters by assignee IDs with support for various matching modes. At least one optional field must be provided. -**Required fields:** `assignee_id` -**Options:** +**Optional fields:** - `assignee_ids` - array of assignee IDs that must ALL be present - `not_assignee_ids` - array of assignee IDs to exclude @@ -2586,10 +2582,9 @@ Example with `none_assignees`: ### `by_weight` -Filters by issue weight (integer value). +Filters by issue weight (integer value). At least one optional field must be provided. -**Required fields:** `weight` -**Options:** +**Optional fields:** - `weight` - exact weight value to match (integer) - `not_weight` - weight value to exclude (integer) @@ -2609,10 +2604,9 @@ Filters by issue weight (integer value). ### `by_health_status` -Filters by health status field. +Filters by health status field. At least one optional field must be provided. -**Required fields:** `health_status` -**Options:** +**Optional fields:** - `health_status` - array of health status IDs to include - `not_health_status` - array of health status IDs to exclude @@ -2634,10 +2628,9 @@ Filters by health status field. ### `by_label_names` -Filters by label names with support for various matching modes and scoped label wildcards. +Filters by label names with support for various matching modes and scoped label wildcards. At least one optional field must be provided. -**Required fields:** `label_names` -**Options:** +**Optional fields:** - `label_names` - array of label names that must ALL be present - `not_label_names` - array of label names to exclude -- GitLab