GitLab Orbitクエリ言語
- プラン: Premium、Ultimate
- 提供形態: GitLab.com
- ステータス: ベータ版
この機能の利用可否は機能フラグによって制御されています。 詳細については、履歴を参照してください。 この機能はテスト目的で利用可能ですが、本番環境での使用には対応していません。
フラットなAPIレスポンスではなくグラフとしてGitLabデータが必要な場合は、GitLab Orbitクエリ言語を使用してください。クエリはJSONオブジェクトで、マッチするエンティティ、辿るリレーションシップ、返すプロパティを指定します。
リクエストエンベロープ
REST APIまたはglab orbit remote queryでクエリを送信する場合は、クエリオブジェクトをトップレベルのqueryフィールドでラップしてください。
{
"query": {
"query_type": "traversal",
"nodes": [{
"id": "mr",
"entity": "MergeRequest",
"node_ids": [12345],
"columns": ["iid", "title", "state"]
}],
"limit": 1
},
"response_format": "raw"
}| フィールド | 必須 | 説明 |
|---|---|---|
query | はい | 以下に記載するクエリオブジェクト。 |
response_format | いいえ | "llm"(省略時のデフォルト。LLM消費向けに最適化されたコンパクトなGOONテキスト)または"raw"(構造化されたJSON)。jqに出力をパイプする場合は"raw"を使用してください。 |
orbit query CLI(ローカルグラフ用)は、エンベロープなしでrawクエリボディを受け取ります。
クエリの形式
すべてのクエリにはquery_typeと、ノードセレクターのnodes配列が必要です。
{
"query_type": "traversal",
"nodes": [{
"id": "mr",
"entity": "MergeRequest",
"node_ids": [12345],
"columns": ["iid", "title", "state"]
}],
"limit": 1
}クエリタイプ
| クエリタイプ | 用途 |
|---|---|
traversal | マッチするノードのフェッチ、またはノード間のリレーションシップの追跡。 |
aggregation | マッチするグラフ結果のカウント、合計、平均、グループ化、またはソート。 |
path_finding | 2つのノードセレクター間の有界パスの検索。 |
neighbors | 1つの有界ノードに接続されたノードの返却。 |
単一ノードのtraversalが検索の形式です。独立したsearchクエリタイプはありません。
トップレベルフィールド
| フィールド | 型 | 説明 |
|---|---|---|
query_type | string | traversal、aggregation、path_finding、またはneighborsのいずれか。 |
nodes | array | ノードセレクター。常に必須。単一ノードクエリ(neighbors、検索形式のtraversal)は1要素の配列を使用します。最大5個。 |
relationships | array | トラバーサルまたは集計のリレーションシップセレクター。最大5個。 |
aggregations | array | 集計定義。aggregationに必須。最大10個。 |
group_by | array | 集計行のグループキー。最大4個。 |
path | object | パス検索の設定。path_findingに必須。 |
neighbors | object | 近傍ルックアップの設定。neighborsに必須。 |
limit | integer | cursorが設定されていない場合に返す最大行数。デフォルト30。最大1000。レスポンスのpagination.truncatedを確認してください。trueの場合、マッチする行がさらに存在します。 |
cursor | object | キーセットページネーション: 最初のページには{"page_size": N}、その後next_cursorがなくなるまで{"page_size": N, "after": "<pagination.next_cursor>"}を使用します。データセットのサイズに関わらず、すべての行に到達できます。トークンは発行したクエリに紐付けられています。 |
order_by | string | ノードプロパティで行をソート: "node.property"(昇順)または"-node.property"(降順)。 |
aggregation_sort | string | 出力列(集計またはグループキーのエイリアス)で集計行をソート: "column"(昇順)または"-column"(降順)。 |
options | object | 表示およびデバッグオプション。 |
ページネーションはリクエスト時にライブデータを読み取るため、スナップショットはありません。各ページは独立してすべての行の最新バージョンを解決し、ソフト削除された行をフィルタリングするため、ページ間でのバージョン変更やトゥームストーンのクリーンアップによって結果がスキップまたは重複することはありません。ソート順でカーソル位置より後に挿入された行は後のページに表示され、カーソルより前に挿入または並び替えられた行は再訪されません。ソートキーがNULLの行は最後にソートされ、他の行と同様にページネーションされます。ページ間でソートキーが変わった行は、スナップショットなしのキーセットページネーションと同様に、2回表示されるか、まったく表示されない場合があります。
ノードセレクター
ノードセレクターはオントロジー内の1つのエンティティタイプを指定します。
| フィールド | 型 | 説明 |
|---|---|---|
id | string | ノードのローカルエイリアス。リレーションシップ、集計、パス、および近傍はこのエイリアスを参照します。 |
entity | string | Project、User、MergeRequest、File、Definitionなどのオントロジーノードタイプ。 |
columns | stringまたはarray | 返すプロパティ。すべての非制限プロパティには"*"を、名前の配列を使用します。省略した場合、GitLab Orbitはエンティティのデフォルト列を返します。 |
filters | object | プロパティフィルター。 |
node_ids | array | マッチする正確なID。整数または数字文字列を受け付けます。最大500個。 |
id_range | object | startとendを持つ包括的なID範囲。 |
id_property | string | node_idsとid_rangeで使用するプロパティ。デフォルトid。 |
グラフIDが既にわかっている場合はnode_idsを使用し、username、full_path、state、pathなどの自然なプロパティがわかっている場合はfiltersを使用してください。
リレーションシップ
リレーションシップはエイリアスでノードセレクターを接続します。
{
"type": "AUTHORED",
"from": "user",
"to": "mr",
"direction": "outgoing"
}| フィールド | 型 | 説明 |
|---|---|---|
type | stringまたはarray | リレーションシップタイプ(1つまたは複数)。有界クエリで任意のリレーションシップが必要な場合のみ"*"を使用してください。 |
from | string | 開始ノードセレクターのエイリアス。 |
to | string | 終了ノードセレクターのエイリアス。 |
direction | string | outgoing、incoming、またはboth。デフォルトoutgoing。 |
hops | array | 包括的な[min, max]ホップ範囲([1, 3]、ちょうど2の場合は[2, 2])。デフォルト[1, 1]。最大3。 |
filters | object | リレーションシッププロパティフィルター。最大5フィルター。 |
例えば、マージリクエストはIN_PROJECTでプロジェクトを指し、ユーザーはAUTHOREDでマージリクエストを指します。
フィルター
フィルターは単純な等値比較を使用できます。
{
"filters": {
"state": "merged"
}
}または演算子オブジェクトを使用できます。同じプロパティに複数の演算子キーを指定するとAND結合になり、範囲指定に使用できます。
{
"filters": {
"created_at": {"gte": "2026-01-01", "lt": "2026-02-01"},
"state": {"in": ["opened", "merged"]}
}
}同じプロパティに演算子を繰り返す場合は、演算子オブジェクトの配列を使用してください: {"title": [{"contains": "foo"}, {"contains": "bar"}]}。
| 演算子 | 用途 |
|---|---|
eq | スカラー値と等しい。 |
gt、gte、lt、lte | 数値、日付、またはタイムスタンプの比較。 |
in | 値が配列内に含まれる。最大100個の値。 |
contains | 文字列が部分文字列を含む。 |
starts_with | 文字列がプレフィックスで始まる。 |
ends_with | 文字列がサフィックスで終わる。 |
is_null | nullチェック。ブール値を受け取ります: falseはnullでない値にマッチします。 |
is_not_null | nullでないチェック。ブール値を受け取ります: falseはnullの値にマッチします。 |
token_match | テキストインデックスが1つのトークンを含む。 |
all_tokens | テキストインデックスがすべてのトークンを含む。 |
any_tokens | テキストインデックスがいずれかのトークンを含む。 |
トークン演算子はテキストインデックスを持つプロパティにのみ機能します。
テキストインデックス付きプロパティ
以下のプロパティはtoken_match、all_tokens、およびany_tokensをサポートしています。
これらの演算子を他のプロパティに使用すると、完全な文字列スキャンにフォールバックするため、処理が遅くなります。
| エンティティ | テキストインデックス付きプロパティ |
|---|---|
Branch | name |
Definition | file_path、fqn、name |
Deployment | ref |
Directory | name、path |
Environment | environment_type、name |
File | name、path |
Finding | description、name |
Group | description、name |
ImportedSymbol | file_path、import_path |
Job | name、ref |
Label | description、title |
MergeRequest | description、source_branch、target_branch、title |
MergeRequestDiffFile | new_path、old_path |
Milestone | description、title |
Note | note |
Pipeline | ref |
Project | description、name |
Runner | name |
Stage | name |
User | name、username |
Vulnerability | description、title |
VulnerabilityIdentifier | external_id、external_type、name |
VulnerabilityOccurrence | description、name |
VulnerabilityScanner | external_id、name |
WorkItem | description、title |
列と仮想列
ほとんどの列はClickHouseのインデックス付きグラフテーブルから取得されます。一部の列は仮想列で、グラフクエリが返された後に別のサービスからGitLab Orbitがフェッチします。
仮想列はcolumnsで明示的にリクエストしてください。path_findingとneighborsで使用されるdynamic_columnsオプションは、外部サービス呼び出しが必要になる可能性があるため、仮想列を除外します。
| エンティティ | 仮想列 | 返す内容 |
|---|---|---|
MergeRequest | diff | マージリクエストの完全な統合差分。 |
MergeRequestDiff | patch | 1つのマージリクエスト差分スナップショットの完全なパッチ。 |
MergeRequestDiffFile | diff | ファイルごとの統合差分テキスト。too_largeがtrueの場合はnullを返します。 |
File | content | ファイルのrawソーステキスト。 |
Definition | content | 1つのインデックス付き定義のソーステキスト。 |
content列はソースコード用です。マージリクエストの差分テキストには、MergeRequest.diff、MergeRequestDiff.patch、またはMergeRequestDiffFile.diffを使用してください。
トラバーサルの例
完全な差分を含む1つのマージリクエストをフェッチする:
{
"query_type": "traversal",
"nodes": [{
"id": "mr",
"entity": "MergeRequest",
"node_ids": [12345],
"columns": ["iid", "title", "state", "diff"]
}],
"limit": 1
}差分スナップショットからファイルごとの差分コンテンツをフェッチする:
{
"query_type": "traversal",
"nodes": [
{
"id": "mr",
"entity": "MergeRequest",
"node_ids": [12345],
"columns": ["iid", "title", "state"]
},
{
"id": "snapshot",
"entity": "MergeRequestDiff",
"columns": ["id", "state", "patch"]
},
{
"id": "file",
"entity": "MergeRequestDiffFile",
"columns": ["new_path", "old_path", "too_large", "diff"]
}
],
"relationships": [
{"type": "HAS_DIFF", "from": "mr", "to": "snapshot"},
{"type": "HAS_FILE", "from": "snapshot", "to": "file"}
],
"limit": 20
}HAS_DIFFはマージリクエストがこれまでに持っていたすべての差分スナップショットを返します(MergeRequestDiff.merge_request_id FK)。HAS_LATEST_DIFFは最新のスナップショットのみを返します(MergeRequest.latest_merge_request_diff_id FK)。これは「マージリクエストが現在どのような状態か」を確認するのに便利ですが、過去の質問には適していません。「あるファイルに触れたすべてのマージリクエスト」を調べるには、すべてのスナップショットに対してHAS_DIFFをトラバースしてください。長期間存在するファイルに対してHAS_LATEST_DIFFを使用すると、過去のカバレッジに関する質問で大幅に過少カウントになる可能性があります。以前のリビジョンでファイルに触れたが最終差分では触れていないMRは、HAS_LATEST_DIFFでは見えません。
MergeRequestDiffFile.old_pathはファイルルックアップに推奨される列です。new_pathはリネームの場合のみold_pathと異なります。old_pathでフィルタリングおよびグループ化することで、MRの履歴全体で同じ行IDが維持されます。merge_request_diff_file.yamlのオントロジーフィールドの説明を参照してください。
ソースファイルのコンテンツをフェッチする:
{
"query_type": "traversal",
"nodes": [{
"id": "file",
"entity": "File",
"filters": {
"path": {"ends_with": "app/models/project.rb"}
},
"columns": ["path", "language", "content"]
}],
"limit": 5
}特定の関数またはクラス定義のソーステキストをフェッチする。content列はファイル全体ではなく、その定義のrawソーステキストのみを返します。完全一致にはfqn(完全修飾名)を使用し、より広い検索にはnameとcontainsを使用してください。
{
"query_type": "traversal",
"nodes": [{
"id": "d",
"entity": "Definition",
"filters": {
"fqn": {"eq": "Gitlab::Auth::authenticate"}
},
"columns": ["name", "fqn", "file_path", "start_line", "end_line", "content"]
}],
"limit": 5
}プロジェクト内のマージ済みマージリクエストを検索する:
{
"query_type": "traversal",
"nodes": [
{
"id": "project",
"entity": "Project",
"filters": {"full_path": "your-group/your-project"},
"columns": ["name", "full_path"]
},
{
"id": "mr",
"entity": "MergeRequest",
"filters": {"state": "merged"},
"columns": ["iid", "title", "state", "merged_at"]
}
],
"relationships": [
{"type": "IN_PROJECT", "from": "mr", "to": "project"}
],
"limit": 25
}1つのマージリクエストに対して実行されたすべてのパイプラインを検索する。マージリクエストのパイプラインタブに表示される内容と一致させるために、常にPipeline.source = "merge_request_event"でフィルタリングしてください。
{
"query_type": "traversal",
"nodes": [{
"id": "p",
"entity": "Pipeline",
"filters": {
"merge_request_id": {"eq": 482908721},
"source": {"eq": "merge_request_event"}
},
"columns": ["id", "status", "source", "sha", "ref", "created_at"]
}],
"order_by": "-p.created_at",
"limit": 100
}merge_request_idはマージリクエストの内部数値idであり、プロジェクトスコープのiidではありません。まずiidとproject_idでフィルタリングするMergeRequestトラバーサルで調べてから、そのidを上記のクエリに使用してください。
Pipeline.merge_request_idとMergeRequest --TRIGGERED--> Pipelineエッジはどちらも、MRのコンテキストで起動されたすべてのCIパイプライン(トップレベルのMRパイプラインがトリガーするダウンストリームの子パイプライン(source = "parent_pipeline")を含む)にMRをリンクします。source = "merge_request_event"フィルターなしでは、親子パイプラインのファンアウトを使用するMRで大幅に過剰カウントになり、MRのパイプラインタブに表示される内容と一致しません。マルチノードクエリでMergeRequest --TRIGGERED--> Pipelineをトラバースする場合も同じフィルターを適用してください。
MergeRequest --HAS_HEAD_PIPELINE--> Pipelineは別のエッジです。マージリクエストのソースブランチの先端に対して実行されている最新の単一パイプラインを指します。パイプラインの履歴ではなく、「現在実行中のもの」を確認する場合に使用してください。
集計
集計クエリはaggregationsを使用します。各集計は、集計対象を値とする単一の関数キーと、オプションのas出力列名を持つオブジェクトです: {"avg": "mr.merge_duration", "as": "avg_dur"}。
| 関数キー | 値 | サポートされるプロパティタイプ |
|---|---|---|
count | "node"(マッチする行をカウント)または"node.property"(null以外の値をカウント) | 任意 |
sum | "node.property" | 数値のみ |
avg | "node.property" | 数値のみ |
min | "node.property" | 数値、文字列、ブール値、Date、またはDateTime |
max | "node.property" | 数値、文字列、ブール値、Date、またはDateTime |
asを省略した場合、出力列名は<function>_<node>(count_mr)または<function>_<node>_<property>(avg_mr_merge_duration)として導出されます。これらの名前をaggregation_sortで参照してください。
sumとavgはDateTimeプロパティをバリデーションエラーで拒否します。日付を集計するにはminまたはmaxを使用してください。
トップレベルのgroup_byを使用して集計行をグループ化します。これはクエリ内のすべての集計に適用されます。個々の集計内にグループ化を入れないでください。
グループキーは以下の形式をサポートしています。
| グループキー | 形式 | 結果の値 |
|---|---|---|
| ノード | "<node-id>"(例: "p") | 各行にネストされたエンティティオブジェクト。 |
| プロパティ | "<node-id>.<property>"(例: "mr.state") | 各行のスカラーバケット値。 |
| 切り捨て日付 | {"key": "<node-id>.<property>", "truncate": "<unit>"} | 単位の開始に切り捨てられたプロパティ値。 |
出力列名は導出されます。ノードキーはノードID(p)を使用し、プロパティキーは<node>_<property>(mr_state)を使用し、切り捨てキーは単位を付加します(mr_created_at_month)。これらの名前をaggregation_sortで参照してください。グループまたは集計の出力名が重複している場合は拒否されます。
導出された名前を使用してください。コンシューマーが特定の列名を必要とする場合のみ、オブジェクト形式のオプションasでリネームしてください: {"key": "mr.state", "as": "state"}、または切り捨てを使用する場合は{"key": "mr.created_at", "truncate": "month", "as": "month"}。
切り捨て単位はminute、hour、day、week、month、quarter、yearで、Date/DateTimeプロパティにのみ適用されます。minuteとhourは、バケットのカーディナリティを制限するためにnode_idsまたは切り捨てプロパティへのフィルターが必要です。
プロパティグループは、呼び出し元が使用を許可されている、実際のClickHouseバックエンドのフィルタリング可能なプロパティを参照する必要があります。仮想フィールドとフィルタリング不可能なフィールドはバリデーション中に拒否されます。
プロジェクトごとのマージ済みマージリクエスト数をカウントする:
{
"query_type": "aggregation",
"nodes": [
{
"id": "project",
"entity": "Project",
"filters": {"full_path": "your-group/your-project"}
},
{
"id": "mr",
"entity": "MergeRequest",
"filters": {"state": "merged"}
}
],
"relationships": [
{"type": "IN_PROJECT", "from": "mr", "to": "project"}
],
"group_by": ["project"],
"aggregations": [
{ "count": "mr", "as": "merged_mrs" }
],
"aggregation_sort": "-merged_mrs",
"limit": 10
}重大度別に検出された脆弱性をカウントする:
{
"query_type": "aggregation",
"nodes": [
{
"id": "v",
"entity": "Vulnerability",
"filters": {"state": "detected"}
}
],
"group_by": ["v.severity"],
"aggregations": [
{ "count": "v", "as": "vulnerability_count" }
],
"aggregation_sort": "-vulnerability_count",
"limit": 10
}集計レスポンスはテーブル形式です。columnsは計算された集計値を、group_columnsはグループ化キーを、rowsはグループ値とメトリクス値を保持します。ノードグループ化された行はグループキーの下にグループ化されたエンティティを格納します。プロパティグループ化された行はグループキーの下にスカラーバケットを格納します。
collectは入力タイプに記載されていますが、現在はバリデーションで拒否されます。
パス検索
パス検索クエリはpathを使用します。
| フィールド | 型 | 説明 |
|---|---|---|
type | string | shortest。 |
from | string | 開始ノードセレクターのエイリアス。 |
to | string | 終了ノードセレクターのエイリアス。 |
max_depth | integer | 最大パス長。最大3。 |
rel_types | array | トラバースするリレーションシップタイプ。両方のエンドポイントがnode_idsを使用する場合を除き必須。 |
両方のエンドポイントはnode_ids、フィルター、または500以下のスパンを持つid_rangeで有界である必要があります。いずれかのエンドポイントがフィルターまたはid_rangeを使用する場合は、rel_typesを指定してください。
{
"query_type": "path_finding",
"nodes": [
{"id": "start", "entity": "Project", "node_ids": [278964]},
{"id": "end", "entity": "User", "node_ids": [1]}
],
"path": {
"type": "shortest",
"from": "start",
"to": "end",
"max_depth": 3,
"rel_types": ["CREATOR", "AUTHORED", "IN_PROJECT"]
},
"limit": 5
}近傍
近傍クエリは1要素のnodes配列とneighborsオブジェクトを使用します。中心ノードはnode_ids、フィルター、または狭いid_rangeで有界である必要があります。
{
"query_type": "neighbors",
"nodes": [{
"id": "mr",
"entity": "MergeRequest",
"node_ids": [12345]
}],
"neighbors": {
"direction": "both",
"rel_types": ["AUTHORED", "IN_PROJECT", "HAS_DIFF"]
},
"options": {
"dynamic_columns": "default"
},
"limit": 25
}動的に検出された近傍またはパスノードのすべての非制限ClickHouseバックエンド列が必要な場合は、options.dynamic_columnsを"*"に設定してください。仮想列はトラバーサルクエリでの明示的なリクエストが引き続き必要です。
バリデーション制限
GitLab OrbitはSQLをコンパイルする前に、広範または曖昧なクエリを拒否します。
| 制限 | 値 |
|---|---|
| クエリあたりのノード数 | 5 |
| クエリあたりのリレーションシップ数 | 5 |
| クエリあたりの集計数 | 10 |
セレクターあたりのnode_ids数 | 500 |
inフィルターの値数 | 100 |
| ノードセレクターあたりの列数 | 50 |
| セレクターあたりのリレーションシップタイプ数 | 10 |
| リレーションシップホップ数 | 3 |
| パスの深さ | 3 |
| ノードあたりのフィルター数 | 10 |
| リレーションシップあたりのフィルター数 | 5 |
トラバーサルおよび集計クエリには、少なくとも1つの選択的なノード(node_ids、フィルター、または100,000以下のスパンを持つid_range)が必要です。
単一ノードのトラバーサルも選択性が必要です。広範なエンティティを検査するには、フィルターを追加するか、IDを指定するか、狭いid_rangeを使用してください。
オプション
| オプション | 説明 |
|---|---|
dynamic_columns | path_findingとneighborsのハイドレーション用。各エンティティのデフォルト列にはdefaultを、すべての非制限ClickHouseバックエンド列には"*"を使用します。デフォルトdefault。 |
include_debug_sql | 呼び出し元が参照を許可されている場合、レスポンスメタデータにコンパイル済みClickHouse SQLを含めます。 |