Skip to content

Commit f338759

Browse files
committed
feat(bigquery): add bigquery_create_vector_index_tree_ah sample to create a TreeAH vector index on embedding column
Problem: The BigQuery documentation (https://cloud.google.com/bigquery/docs/vector-index) needs a standalone, tested Python code sample demonstrating how to create a TreeAH vector index on embedding column (region tag `bigquery_create_vector_index_tree_ah`). Solution: - Add `create_vector_index_tree_ah(project_id: str, dataset_id: str, table_id: str) -> None` in `bigquery/vector_search/bigquery_create_vector_index_tree_ah.py` (Create a ScaNN-based TREE_AH vector index on an embedding column in BigQuery using CREATE OR REPLACE VECTOR INDEX.) - Add unit tests (`bigquery/vector_search/bigquery_create_vector_index_tree_ah_test.py`) covering both the success path and API error handling (`GoogleAPICallError`)
1 parent 186be98 commit f338759

5 files changed

Lines changed: 174 additions & 0 deletions

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START bigquery_create_vector_index_tree_ah]
16+
import sys
17+
18+
from google.api_core import exceptions
19+
from google.cloud import bigquery
20+
21+
22+
def create_vector_index_tree_ah(
23+
project_id: str,
24+
dataset_id: str,
25+
table_id: str,
26+
) -> None:
27+
"""Creates a TreeAH vector index on an embedding column in a BigQuery table.
28+
29+
Args:
30+
project_id: Google Cloud project ID (for example, 'example-project').
31+
dataset_id: BigQuery dataset ID containing the target table
32+
(for example, 'example_dataset').
33+
table_id: BigQuery table ID containing the embedding column
34+
(for example, 'example_embeddings').
35+
"""
36+
client = bigquery.Client(project=project_id)
37+
index_name = "example_tree_ah_index"
38+
table_ref = f"{project_id}.{dataset_id}.{table_id}"
39+
# TreeAH indexes use asymmetric hashing optimized for batch and single-query vector search.
40+
sql = f"""
41+
CREATE OR REPLACE VECTOR INDEX `{index_name}`
42+
ON `{table_ref}`(embedding)
43+
OPTIONS(
44+
index_type = 'TREE_AH',
45+
distance_type = 'COSINE',
46+
tree_ah_options = '{{"normalization_type": "L2"}}'
47+
);
48+
"""
49+
50+
try:
51+
print(f"Creating TreeAH vector index {index_name} on table: {table_ref}")
52+
query_job = client.query(sql)
53+
query_job.result()
54+
except exceptions.NotFound as err:
55+
print(
56+
f"error: table '{table_id}' or dataset '{dataset_id}' not found in "
57+
f"project '{project_id}' when creating index '{index_name}': {err.message}",
58+
file=sys.stderr,
59+
)
60+
return
61+
except exceptions.GoogleAPICallError as err:
62+
print(
63+
f"error: failed to create TreeAH vector index '{index_name}' on table "
64+
f"'{table_id}' in dataset '{dataset_id}' for project '{project_id}': {err.message}",
65+
file=sys.stderr,
66+
)
67+
return
68+
69+
print(f"Resource ID: {table_ref}")
70+
print(f"Index Name: {index_name}")
71+
print("Index Type: TREE_AH")
72+
print(f"Job ID: {query_job.job_id}")
73+
print(f"Statement Type: {query_job.statement_type}")
74+
75+
76+
# [END bigquery_create_vector_index_tree_ah]
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from unittest import mock
16+
17+
import bigquery_create_vector_index_tree_ah
18+
from google.api_core import exceptions
19+
import pytest
20+
21+
22+
def test_create_vector_index_tree_ah_success(
23+
monkeypatch: pytest.MonkeyPatch,
24+
capsys: pytest.CaptureFixture[str],
25+
) -> None:
26+
mock_client = mock.MagicMock()
27+
mock_job = mock.MagicMock()
28+
mock_job.job_id = "example-job-123"
29+
mock_job.statement_type = "CREATE_VECTOR_INDEX"
30+
mock_client.query.return_value = mock_job
31+
monkeypatch.setattr(
32+
bigquery_create_vector_index_tree_ah.bigquery,
33+
"Client",
34+
lambda project=None: mock_client,
35+
)
36+
37+
bigquery_create_vector_index_tree_ah.create_vector_index_tree_ah(
38+
project_id="example-project",
39+
dataset_id="example_dataset",
40+
table_id="example_embeddings",
41+
)
42+
43+
captured = capsys.readouterr()
44+
assert (
45+
"Resource ID: example-project.example_dataset.example_embeddings"
46+
in captured.out
47+
)
48+
assert "Index Name: example_tree_ah_index" in captured.out
49+
assert "Index Type: TREE_AH" in captured.out
50+
assert mock_client.query.called
51+
52+
53+
def test_create_vector_index_tree_ah_error(
54+
monkeypatch: pytest.MonkeyPatch,
55+
capsys: pytest.CaptureFixture[str],
56+
) -> None:
57+
mock_client = mock.MagicMock()
58+
mock_client.query.side_effect = exceptions.NotFound("ddl error")
59+
monkeypatch.setattr(
60+
bigquery_create_vector_index_tree_ah.bigquery,
61+
"Client",
62+
lambda project=None: mock_client,
63+
)
64+
65+
bigquery_create_vector_index_tree_ah.create_vector_index_tree_ah(
66+
project_id="example-project",
67+
dataset_id="example_dataset",
68+
table_id="example_embeddings",
69+
)
70+
71+
captured = capsys.readouterr()
72+
assert "error:" in captured.err
73+
assert "example_tree_ah_index" in captured.err
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
TEST_CONFIG_OVERRIDE = {
16+
# You can opt out from the test for specific Python versions.
17+
"ignored_versions": ["2.7", "3.7", "3.8", "3.9", "3.10", "3.11"],
18+
# Enforce type hints on new samples.
19+
"enforce_type_hints": True,
20+
"gcloud_project_env": "GOOGLE_CLOUD_PROJECT",
21+
"pip_version_override": None,
22+
"envs": {},
23+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest==9.0.3; python_version >= "3.10"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
google-cloud-bigquery==3.47.0

0 commit comments

Comments
 (0)