jira-search

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Jira Search Skill

Jira 搜索技能

Purpose

用途

Search for issues using JQL (Jira Query Language). Supports filtering, pagination, and field selection.
使用JQL(Jira查询语言)搜索问题。支持筛选、分页和字段选择。

When to Use

适用场景

  • Searching issues by project, status, assignee, date
  • Building issue lists and reports
  • Finding specific issues by criteria
  • Bulk operations on filtered issues
  • 按项目、状态、经办人、日期搜索问题
  • 生成问题列表和报表
  • 根据条件查找特定问题
  • 对筛选后的问题执行批量操作

Prerequisites

前置条件

  • Authenticated JiraClient (see jira-auth skill)
  • Project access permissions
  • 已认证的JiraClient(参考jira-auth技能)
  • 项目访问权限

Implementation Pattern

实现模式

Step 1: Define Search Types

步骤1:定义搜索类型

typescript
interface SearchOptions {
  jql: string;
  startAt?: number;
  maxResults?: number;
  fields?: string[];
  expand?: string[];
}

interface SearchResponse {
  startAt: number;
  maxResults: number;
  total: number;
  issues: JiraIssue[];
}
typescript
interface SearchOptions {
  jql: string;
  startAt?: number;
  maxResults?: number;
  fields?: string[];
  expand?: string[];
}

interface SearchResponse {
  startAt: number;
  maxResults: number;
  total: number;
  issues: JiraIssue[];
}

Step 2: Basic Search

步骤2:基础搜索

typescript
async function searchIssues(
  client: JiraClient,
  options: SearchOptions
): Promise<SearchResponse> {
  return client.request<SearchResponse>('/search', {
    method: 'POST',
    body: JSON.stringify({
      jql: options.jql,
      startAt: options.startAt ?? 0,
      maxResults: options.maxResults ?? 50,
      fields: options.fields ?? ['key', 'summary', 'status', 'assignee', 'created'],
      expand: options.expand,
    }),
  });
}
typescript
async function searchIssues(
  client: JiraClient,
  options: SearchOptions
): Promise<SearchResponse> {
  return client.request<SearchResponse>('/search', {
    method: 'POST',
    body: JSON.stringify({
      jql: options.jql,
      startAt: options.startAt ?? 0,
      maxResults: options.maxResults ?? 50,
      fields: options.fields ?? ['key', 'summary', 'status', 'assignee', 'created'],
      expand: options.expand,
    }),
  });
}

Step 3: Search All (Paginated)

步骤3:全量搜索(分页)

typescript
async function searchAllIssues(
  client: JiraClient,
  jql: string,
  fields: string[] = ['key', 'summary', 'status']
): Promise<JiraIssue[]> {
  const allIssues: JiraIssue[] = [];
  let startAt = 0;
  const maxResults = 100;

  while (true) {
    const response = await searchIssues(client, {
      jql,
      startAt,
      maxResults,
      fields,
    });

    allIssues.push(...response.issues);

    if (startAt + response.issues.length >= response.total) {
      break;
    }

    startAt += maxResults;
  }

  return allIssues;
}
typescript
async function searchAllIssues(
  client: JiraClient,
  jql: string,
  fields: string[] = ['key', 'summary', 'status']
): Promise<JiraIssue[]> {
  const allIssues: JiraIssue[] = [];
  let startAt = 0;
  const maxResults = 100;

  while (true) {
    const response = await searchIssues(client, {
      jql,
      startAt,
      maxResults,
      fields,
    });

    allIssues.push(...response.issues);

    if (startAt + response.issues.length >= response.total) {
      break;
    }

    startAt += maxResults;
  }

  return allIssues;
}

Step 4: Common Search Builders

步骤4:常用搜索构建器

typescript
// Search by project
function searchByProject(projectKey: string): string {
  return `project = ${projectKey}`;
}

// Search by status
function searchByStatus(status: string | string[]): string {
  if (Array.isArray(status)) {
    return `status IN (${status.map(s => `'${s}'`).join(', ')})`;
  }
  return `status = '${status}'`;
}

// Search by assignee
function searchByAssignee(accountId: string): string {
  return `assignee = '${accountId}'`;
}

// Search my issues
function searchMyIssues(): string {
  return `assignee = currentUser()`;
}

// Search by date range
function searchByCreatedDate(daysAgo: number): string {
  return `created >= -${daysAgo}d`;
}

// Combine conditions
function combineJql(...conditions: string[]): string {
  return conditions.join(' AND ');
}
typescript
// Search by project
function searchByProject(projectKey: string): string {
  return `project = ${projectKey}`;
}

// Search by status
function searchByStatus(status: string | string[]): string {
  if (Array.isArray(status)) {
    return `status IN (${status.map(s => `'${s}'`).join(', ')})`;
  }
  return `status = '${status}'`;
}

// Search by assignee
function searchByAssignee(accountId: string): string {
  return `assignee = '${accountId}'`;
}

// Search my issues
function searchMyIssues(): string {
  return `assignee = currentUser()`;
}

// Search by date range
function searchByCreatedDate(daysAgo: number): string {
  return `created >= -${daysAgo}d`;
}

// Combine conditions
function combineJql(...conditions: string[]): string {
  return conditions.join(' AND ');
}

Step 5: Advanced Search Examples

步骤5:高级搜索示例

typescript
// Find all open issues in project
async function findOpenIssues(client: JiraClient, projectKey: string) {
  return searchAllIssues(
    client,
    combineJql(
      searchByProject(projectKey),
      `status NOT IN (Done, Closed)`
    )
  );
}

// Find my recent issues
async function findMyRecentIssues(client: JiraClient, daysAgo: number = 7) {
  return searchAllIssues(
    client,
    combineJql(
      searchMyIssues(),
      searchByCreatedDate(daysAgo)
    )
  );
}

// Find issues by label
async function findByLabel(client: JiraClient, projectKey: string, label: string) {
  return searchAllIssues(
    client,
    combineJql(
      searchByProject(projectKey),
      `labels = '${label}'`
    )
  );
}

// Find unassigned issues
async function findUnassigned(client: JiraClient, projectKey: string) {
  return searchAllIssues(
    client,
    combineJql(
      searchByProject(projectKey),
      `assignee IS EMPTY`
    )
  );
}
typescript
// Find all open issues in project
async function findOpenIssues(client: JiraClient, projectKey: string) {
  return searchAllIssues(
    client,
    combineJql(
      searchByProject(projectKey),
      `status NOT IN (Done, Closed)`
    )
  );
}

// Find my recent issues
async function findMyRecentIssues(client: JiraClient, daysAgo: number = 7) {
  return searchAllIssues(
    client,
    combineJql(
      searchMyIssues(),
      searchByCreatedDate(daysAgo)
    )
  );
}

// Find issues by label
async function findByLabel(client: JiraClient, projectKey: string, label: string) {
  return searchAllIssues(
    client,
    combineJql(
      searchByProject(projectKey),
      `labels = '${label}'`
    )
  );
}

// Find unassigned issues
async function findUnassigned(client: JiraClient, projectKey: string) {
  return searchAllIssues(
    client,
    combineJql(
      searchByProject(projectKey),
      `assignee IS EMPTY`
    )
  );
}

JQL Quick Reference

JQL 快速参考

Operators

运算符

OperatorExampleDescription
=
status = Done
Equals
!=
status != Done
Not equals
IN
status IN (Done, Closed)
One of
NOT IN
status NOT IN (Done)
Not one of
~
summary ~ "bug"
Contains
IS EMPTY
assignee IS EMPTY
Is null
IS NOT EMPTY
assignee IS NOT EMPTY
Is not null
>=
created >= -7d
Greater/equal
<=
created <= 2025-01-01
Less/equal
运算符示例说明
=
status = Done
等于
!=
status != Done
不等于
IN
status IN (Done, Closed)
属于
NOT IN
status NOT IN (Done)
不属于
~
summary ~ "bug"
包含
IS EMPTY
assignee IS EMPTY
为空
IS NOT EMPTY
assignee IS NOT EMPTY
不为空
>=
created >= -7d
大于等于
<=
created <= 2025-01-01
小于等于

Date Formats

日期格式

FormatExampleDescription
Relative
-7d
7 days ago
Relative
-2w
2 weeks ago
Relative
-1m
1 month ago
Absolute
2025-01-15
Specific date
Function
startOfDay()
Today midnight
Function
startOfWeek()
Monday
格式示例说明
相对日期
-7d
7天前
相对日期
-2w
2周前
相对日期
-1m
1个月前
绝对日期
2025-01-15
特定日期
函数
startOfDay()
今日午夜
函数
startOfWeek()
周一

Common JQL Patterns

常用JQL模式

jql
undefined
jql
undefined

All issues in project

All issues in project

project = SCRUM
project = SCRUM

Open issues

Open issues

project = SCRUM AND status != Done
project = SCRUM AND status != Done

My issues

My issues

assignee = currentUser()
assignee = currentUser()

High priority open issues

High priority open issues

project = SCRUM AND priority = High AND status != Done
project = SCRUM AND priority = High AND status != Done

Created this week

Created this week

project = SCRUM AND created >= startOfWeek()
project = SCRUM AND created >= startOfWeek()

Updated recently

Updated recently

project = SCRUM AND updated >= -7d
project = SCRUM AND updated >= -7d

Unassigned bugs

Unassigned bugs

project = SCRUM AND issuetype = Bug AND assignee IS EMPTY
project = SCRUM AND issuetype = Bug AND assignee IS EMPTY

Issues with specific label

Issues with specific label

project = SCRUM AND labels = "urgent"
project = SCRUM AND labels = "urgent"

Text search in summary

Text search in summary

project = SCRUM AND summary ~ "authentication"
undefined
project = SCRUM AND summary ~ "authentication"
undefined

curl Examples

curl 示例

Basic Search

基础搜索

bash
curl -X POST "$JIRA_BASE_URL/rest/api/3/search" \
  -H "Authorization: Basic $(echo -n 'email:token' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "jql": "project = SCRUM AND status != Done",
    "startAt": 0,
    "maxResults": 50,
    "fields": ["key", "summary", "status", "assignee"]
  }'
bash
curl -X POST "$JIRA_BASE_URL/rest/api/3/search" \
  -H "Authorization: Basic $(echo -n 'email:token' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "jql": "project = SCRUM AND status != Done",
    "startAt": 0,
    "maxResults": 50,
    "fields": ["key", "summary", "status", "assignee"]
  }'

Search with Pagination

分页搜索

bash
curl -X POST "$JIRA_BASE_URL/rest/api/3/search" \
  -H "Authorization: Basic $(echo -n 'email:token' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "jql": "project = SCRUM",
    "startAt": 50,
    "maxResults": 50,
    "fields": ["key", "summary"]
  }'
bash
curl -X POST "$JIRA_BASE_URL/rest/api/3/search" \
  -H "Authorization: Basic $(echo -n 'email:token' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "jql": "project = SCRUM",
    "startAt": 50,
    "maxResults": 50,
    "fields": ["key", "summary"]
  }'

Search with Changelog Expand

包含变更日志的搜索

bash
curl -X POST "$JIRA_BASE_URL/rest/api/3/search" \
  -H "Authorization: Basic $(echo -n 'email:token' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "jql": "project = SCRUM AND updated >= -7d",
    "maxResults": 50,
    "fields": ["key", "summary", "status"],
    "expand": ["changelog"]
  }'
bash
curl -X POST "$JIRA_BASE_URL/rest/api/3/search" \
  -H "Authorization: Basic $(echo -n 'email:token' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "jql": "project = SCRUM AND updated >= -7d",
    "maxResults": 50,
    "fields": ["key", "summary", "status"],
    "expand": ["changelog"]
  }'

Response Structure

响应结构

json
{
  "startAt": 0,
  "maxResults": 50,
  "total": 150,
  "issues": [
    {
      "id": "10001",
      "key": "SCRUM-1",
      "self": "$JIRA_BASE_URL/rest/api/3/issue/10001",
      "fields": {
        "summary": "Issue summary",
        "status": { "name": "To Do" },
        "assignee": { "displayName": "John Doe" }
      }
    }
  ]
}
json
{
  "startAt": 0,
  "maxResults": 50,
  "total": 150,
  "issues": [
    {
      "id": "10001",
      "key": "SCRUM-1",
      "self": "$JIRA_BASE_URL/rest/api/3/issue/10001",
      "fields": {
        "summary": "Issue summary",
        "status": { "name": "To Do" },
        "assignee": { "displayName": "John Doe" }
      }
    }
  ]
}

Pagination Formula

分页公式

Total pages = ceil(total / maxResults)
Current page = floor(startAt / maxResults) + 1
Has more = (startAt + issues.length) < total
Next startAt = startAt + maxResults
Total pages = ceil(total / maxResults)
Current page = floor(startAt / maxResults) + 1
Has more = (startAt + issues.length) < total
Next startAt = startAt + maxResults

Common Mistakes

常见错误

  • Not quoting status values with spaces
  • Using email instead of accountId for assignee
  • Forgetting pagination for large result sets
  • Not escaping special characters in search text
  • 未给包含空格的状态值添加引号
  • 使用邮箱而非accountId指定经办人
  • 处理大量结果集时忘记分页
  • 未对搜索文本中的特殊字符进行转义

References

参考链接

Version History

版本历史

  • 2025-12-10: Created
  • 2025-12-10: 创建