Repository navigation
feat(bigquery): add bigquery_search_subset_columns sample to search a… #14737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| # Copyright 2026 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # [START bigquery_search_subset_columns] | ||
| import sys | ||
|
|
||
| from google.api_core import exceptions | ||
| from google.cloud import bigquery | ||
|
|
||
|
|
||
| def search_subset_columns( | ||
| project_id: str, | ||
| ) -> None: | ||
| """Searches a specific subset of columns in a BigQuery table using SEARCH. | ||
|
|
||
| Args: | ||
| project_id: Google Cloud project ID used to bill the query job | ||
| (for example, 'example-project'). | ||
| """ | ||
| client = bigquery.Client(project=project_id) | ||
| # Query the public theLook eCommerce dataset in bigquery-public-data | ||
| # (https://cloud.google.com/bigquery/public-data). | ||
| table_ref = "bigquery-public-data.thelook_ecommerce.users" | ||
| # Restrict SEARCH to street_address and city by passing a parenthesized column tuple. | ||
| search_query = "Nelson Apt" | ||
| job_config = bigquery.QueryJobConfig( | ||
| query_parameters=[ | ||
| bigquery.ScalarQueryParameter("search_query", "STRING", search_query), | ||
| ] | ||
| ) | ||
| sql = f""" | ||
| SELECT | ||
| u.id, | ||
| u.first_name, | ||
| u.last_name, | ||
| u.street_address, | ||
| u.city | ||
| FROM `{table_ref}` AS u | ||
| WHERE SEARCH((u.street_address, u.city), @search_query) | ||
| ORDER BY u.id ASC | ||
| LIMIT 10; | ||
| """ | ||
|
|
||
| try: | ||
| print(f"Searching subset of columns in {table_ref} for term: {search_query}") | ||
| query_job = client.query(sql, job_config=job_config) | ||
| rows = list(query_job.result()) | ||
| except exceptions.NotFound as err: | ||
| print( | ||
| f"error: table '{table_ref}' not found when querying from project " | ||
| f"'{project_id}': {err.message}", | ||
| file=sys.stderr, | ||
| ) | ||
| return | ||
| except exceptions.GoogleAPICallError as err: | ||
| print( | ||
| f"error: failed to search columns in '{table_ref}' for project " | ||
| f"'{project_id}': {err.message}", | ||
| file=sys.stderr, | ||
| ) | ||
| return | ||
|
|
||
| print(f"Resource ID: {table_ref}") | ||
| print(f"Job ID: {query_job.job_id}") | ||
| print(f"Matching Rows: {len(rows)}") | ||
| print(f"Search Term: {search_query}") | ||
|
|
||
|
|
||
| # [END bigquery_search_subset_columns] |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,67 @@ | ||||||||||||||||||||||
| # Copyright 2026 Google LLC | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||||||||||||||||||||
| # you may not use this file except in compliance with the License. | ||||||||||||||||||||||
| # You may obtain a copy of the License at | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # Unless required by applicable law or agreed to in writing, software | ||||||||||||||||||||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||||||||||||||||||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||||||||||||||||||
| # See the License for the specific language governing permissions and | ||||||||||||||||||||||
| # limitations under the License. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| from unittest import mock | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import bigquery_search_subset_columns | ||||||||||||||||||||||
| from google.api_core import exceptions | ||||||||||||||||||||||
| import pytest | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def test_search_subset_columns_success( | ||||||||||||||||||||||
| monkeypatch: pytest.MonkeyPatch, | ||||||||||||||||||||||
| capsys: pytest.CaptureFixture[str], | ||||||||||||||||||||||
| ) -> None: | ||||||||||||||||||||||
| mock_client = mock.MagicMock() | ||||||||||||||||||||||
| mock_job = mock.MagicMock() | ||||||||||||||||||||||
| mock_job.job_id = "example-job-123" | ||||||||||||||||||||||
| mock_job.result.return_value = [mock.MagicMock()] | ||||||||||||||||||||||
| mock_client.query.return_value = mock_job | ||||||||||||||||||||||
| monkeypatch.setattr( | ||||||||||||||||||||||
| bigquery_search_subset_columns.bigquery, | ||||||||||||||||||||||
| "Client", | ||||||||||||||||||||||
| lambda project=None: mock_client, | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| bigquery_search_subset_columns.search_subset_columns( | ||||||||||||||||||||||
| project_id="example-project", | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| captured = capsys.readouterr() | ||||||||||||||||||||||
| assert "Resource ID: bigquery-public-data.thelook_ecommerce.users" in captured.out | ||||||||||||||||||||||
| assert "Matching Rows: 1" in captured.out | ||||||||||||||||||||||
| assert mock_client.query.called | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def test_search_subset_columns_error( | ||||||||||||||||||||||
| monkeypatch: pytest.MonkeyPatch, | ||||||||||||||||||||||
| capsys: pytest.CaptureFixture[str], | ||||||||||||||||||||||
| ) -> None: | ||||||||||||||||||||||
| mock_client = mock.MagicMock() | ||||||||||||||||||||||
| mock_job = mock.MagicMock() | ||||||||||||||||||||||
| mock_job.result.side_effect = exceptions.NotFound("resource error") | ||||||||||||||||||||||
| mock_client.query.return_value = mock_job | ||||||||||||||||||||||
| monkeypatch.setattr( | ||||||||||||||||||||||
| bigquery_search_subset_columns.bigquery, | ||||||||||||||||||||||
| "Client", | ||||||||||||||||||||||
| lambda project=None: mock_client, | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
Comment on lines
+55
to
+59
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using a lambda with a specific signature like
Suggested change
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| bigquery_search_subset_columns.search_subset_columns( | ||||||||||||||||||||||
| project_id="example-project", | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| captured = capsys.readouterr() | ||||||||||||||||||||||
| assert "error:" in captured.err | ||||||||||||||||||||||
| assert "example-project" in captured.err | ||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # Copyright 2026 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| TEST_CONFIG_OVERRIDE = { | ||
| # You can opt out from the test for specific Python versions. | ||
| "ignored_versions": ["2.7", "3.7", "3.8", "3.9", "3.10", "3.11"], | ||
| # Enforce type hints on new samples. | ||
| "enforce_type_hints": True, | ||
| "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", | ||
| "pip_version_override": None, | ||
| "envs": {}, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| pytest==9.0.3; python_version >= "3.10" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| google-cloud-bigquery==3.47.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a lambda with a specific signature like
lambda project=Noneto mock a class constructor is fragile. If the initialization arguments ofbigquery.Clientchange or if other arguments are passed, this will raise aTypeError. Usingmock.MagicMock(return_value=mock_client)is the standard, robust way to mock a class constructor in Python.