GoogleSQL for SecOps supports the following search functions.
Function list
| Name | Summary |
|---|---|
VECTOR_SEARCH
|
Performs a semantic search on embeddings to find similar entities. |
VECTOR_SEARCH
VECTOR_SEARCH(
TABLE base_table,
column_to_search,
TABLE query_table,
[, query_column_to_search => string_value]
[, top_k => int64_value]
[, distance_type => string_value]
[, max_distance => double_value]
[, options => ]
)
Description
Searches embeddings in multiple rows in a table, known as batch vector
searches, to find semantically similar entities. The VECTOR_SEARCH function
returns the nearest neighbors from the base_table for each row in the
query_table, based on the distance function applied to their vector
embeddings.
Embeddings are high-dimensional numerical vectors that represent a given entity, like a piece of text or an audio file. Machine learning (ML) models use embeddings to encode semantics about such entities to make it easier to reason about and compare them. For example, a common operation in clustering, classification, and recommendation models is to measure the distance between vectors in an embedding space to find items that are most semantically similar.
Definitions
base_table: The table to search for nearest neighbor embeddings.column_to_search: The name of the base table column to search for nearest neighbor embeddings. The column must be of typeARRAY<DOUBLE>,ARRAY<FLOAT>, orSTRING.query_table: Query data containing the search field.query_column_to_search: A named argument with aSTRINGvalue.string_valuespecifies the name of the column in the query table or statement that contains the strings or embeddings for which to find nearest neighbors.The value must be a single column name with valid types as
ARRAY<DOUBLE>,ARRAY<FLOAT>, orSTRING. The data type of this column must match thecolumn_to_searchcolumn type.If the type is
ARRAY<DOUBLE>orARRAY<FLOAT>, then all element values must be non-NULL. The dimension of all elements in this column must match the search column inbase_table.If the column is of type
STRING, embeddings are automatically generated using the same model associated withcolumn_to_searchinbase_table. System-specific metadata must be present to indicate how to generate the embeddings synchronously for the query. If embedding generation fails for the query, theVECTOR_SEARCHquery fails.If you don't specify
query_column_to_search, the function uses thecolumn_to_searchvalue or picks the most appropriate column.
top_k: A named argument with anINT64value.top_k_valuespecifies the number of nearest neighbors to return. The default is 10. If the value is negative, all values are counted as neighbors and returned.distance_type: A named argument with aSTRINGvalue.string_valuespecifies the type of metric to use to compute the distance between two vectors. Supported distance types areEUCLIDEAN(default),COSINE, andDOT_PRODUCT.max_distance: A named argument with aDOUBLEvalue.double_valuespecifies the exclusive upper bound on the distance of returned neighbors. Neighbors with distances exceeding this value are filtered out. Whenmax_distanceis used with aDOT_PRODUCTdistance type, themax_distancemust be equivalent to-1 * DOT_PRODUCTto get the correct upper bound. Themax_distanceis useful for reducing data volume.options: A named argument with a value.
Output
For each row in the query data, the output contains multiple rows from the
base table that satisfy the search criteria. The number of results rows per
query table row is either 10 or the top_k value if it's specified. The
order of the output isn't guaranteed.
The output includes the following columns:
query: ASTRUCTvalue that contains all selected columns from the query data.base: ASTRUCTvalue that contains all columns frombase_tablefor the neighbor row.distance: ADOUBLEvalue that represents the distance between the base data and the query data. If thedistance_typeargument isDOT_PRODUCT, the returned distance value is a negativeDOT_PRODUCTvalue between the query and base vector.
Examples
For the first set of examples that follow, add the following sample data at the top of each query:
-- Sample data for the base table
WITH Songs AS (
SELECT 1 AS song_id, 'Bohemian Rhapsody' AS title, 'Queen' AS artist, 'A Night at the Opera' AS album, 'Rock' AS genre, [0.1, 0.9, 0.2] AS song_embedding
UNION ALL
SELECT 2, 'Like a Rolling Stone' AS title, 'Bob Dylan' AS artist, 'Highway 61 Revisited' AS album, 'Rock' AS genre, [0.2, 0.8, 0.3] AS song_embedding
UNION ALL
SELECT 3, 'Stairway to Heaven' AS title, 'Led Zeppelin' AS artist, 'Led Zeppelin IV' AS album, 'Rock' AS genre, [0.15, 0.85, 0.25] AS song_embedding
UNION ALL
SELECT 4, 'What a Wonderful World' AS title, 'Louis Armstrong' AS artist, 'What a Wonderful World' AS album, 'Jazz' AS genre, [0.8, 0.1, 0.9] AS song_embedding
UNION ALL
SELECT 5, 'So What' AS title, 'Miles Davis' AS artist, 'Kind of Blue' AS album, 'Jazz' AS genre, [0.9, 0.2, 0.8] AS song_embedding
UNION ALL
SELECT 6, 'Hallelujah' AS title, 'Leonard Cohen' AS artist, 'Various Positions' AS album, 'Folk' AS genre, [0.5, 0.5, 0.5] AS song_embedding
),
-- Sample data for the query table
QuerySimilarSongs AS (
SELECT 'query1' AS query_id, [0.12, 0.88, 0.22] AS search_embedding, 'Classic Rock' AS description
UNION ALL
SELECT 'query2', [0.85, 0.15, 0.85], 'Smooth Jazz'
)
The following examples search the song_embedding column of the Songs base
table for the top two embeddings that match each row in the QuerySimilarSongs
query table. Each example uses a different distance_type value.
SELECT
query.query_id,
query.description AS query_description,
base.title,
base.artist,
distance
FROM VECTOR_SEARCH(
TABLE Songs,
'song_embedding',
TABLE QuerySimilarSongs,
query_column_to_search => 'search_embedding',
top_k => 2
-- No distance type specified, so defaults to EUCLIDEAN.
);
/*----------+-------------------+------------------------+-----------------+----------+
| query_id | query_description | title | artist | distance |
+----------+-------------------+------------------------+-----------------+----------+
| query1 | Classic Rock | Bohemian Rhapsody | Queen | 0.0034 |
| query1 | Classic Rock | Stairway to Heaven | Led Zeppelin | 0.0519 |
| query2 | Smooth Jazz | What a Wonderful World | Louis Armstrong | 0.086 |
| query2 | Smooth Jazz | So What | Miles Davis | 0.0860 |
+----------+-------------------+------------------------+-----------------+----------*/
SELECT
query.query_id,
query.description AS query_description,
base.title,
base.artist,
distance
FROM VECTOR_SEARCH(
TABLE Songs,
'song_embedding',
TABLE QuerySimilarSongs,
query_column_to_search => 'search_embedding',
top_k => 2,
-- COSINE distance type
distance_type => 'COSINE'
);
/*----------+-------------------+------------------------+-----------------+------------+
| query_id | query_description | title | artist | distance |
+----------+-------------------+------------------------+-----------------+------------+
| query1 | Classic Rock | Bohemian Rhapsody | Queen | 0.00061686 |
| query1 | Classic Rock | Stairway to Heaven | Led Zeppelin | 0.00147881 |
| query2 | Smooth Jazz | What a Wonderful World | Louis Armstrong | 0.00250705 |
| query2 | Smooth Jazz | So What | Miles Davis | 0.0025863 |
+----------+-------------------+------------------------+-----------------+------------*/
SELECT
query.query_id,
query.description AS query_description,
base.title,
base.artist,
distance -- Negative dot product value
FROM VECTOR_SEARCH(
TABLE Songs,
'song_embedding',
TABLE QuerySimilarSongs,
query_column_to_search => 'search_embedding',
top_k => 2,
-- DOT_PRODUCT distance type as a negative DOT_PRODUCT value between the
-- query and base vector. Smaller values (more negative) are more similar.
distance_type => 'DOT_PRODUCT'
);
/*----------+-------------------+------------------------+-----------------+----------+
| query_id | query_description | title | artist | distance |
+----------+-------------------+------------------------+-----------------+----------+
| query1 | Classic Rock | Bohemian Rhapsody | Queen | -0.848 |
| query1 | Classic Rock | Stairway to Heaven | Led Zeppelin | -0.821 |
| query2 | Smooth Jazz | So What | Miles Davis | -1.475 |
| query2 | Smooth Jazz | What a Wonderful World | Louis Armstrong | -1.46 |
+----------+-------------------+------------------------+-----------------+----------*/
For the next set of examples that follow, add the following sample data at the top of each query:
-- Sample data for the Songs table
WITH Songs AS (
SELECT 1 AS song_id, 'Bohemian Rhapsody' AS title, 'Queen' AS artist, 'A Night at the Opera' AS album, 'Rock' AS genre, [0.1, 0.9, 0.2] AS song_embedding
UNION ALL
SELECT 2, 'Like a Rolling Stone' AS title, 'Bob Dylan' AS artist, 'Highway 61 Revisited' AS album, 'Rock' AS genre, [0.2, 0.8, 0.3] AS song_embedding
UNION ALL
SELECT 3, 'Stairway to Heaven' AS title, 'Led Zeppelin' AS artist, 'Led Zeppelin IV' AS album, 'Rock' AS genre, [0.15, 0.85, 0.25] AS song_embedding
UNION ALL
SELECT 4, 'What a Wonderful World' AS title, 'Louis Armstrong' AS artist, 'What a Wonderful World' AS album, 'Jazz' AS genre, [0.8, 0.1, 0.9] AS song_embedding
UNION ALL
SELECT 5, 'So What' AS title, 'Miles Davis' AS artist, 'Kind of Blue' AS album, 'Jazz' AS genre, [0.9, 0.2, 0.8] AS song_embedding
UNION ALL
SELECT 6, 'Hallelujah' AS title, 'Leonard Cohen' AS artist, 'Various Positions' AS album, 'Folk' AS genre, [0.5, 0.5, 0.5] AS song_embedding
),
-- Sample data for the query table
QuerySimilarSongs AS (
SELECT 'queryA' AS query_id, [0.6, 0.4, 0.4] AS search_embedding, 'Folk Rock' AS description
UNION ALL
SELECT 'queryB', [0.1, 0.1, 0.8], 'Mellow Jazz'
)
The following example searches the song_embedding column of the Songs base
table for embeddings that are within a EUCLIDEAN maximum distance of 0.6 for
each row in the QuerySimilarSongs query table.
SELECT
query.query_id,
query.description AS query_description,
base.title,
base.artist,
distance
FROM VECTOR_SEARCH(
TABLE Songs,
'song_embedding',
TABLE QuerySimilarSongs,
query_column_to_search => 'search_embedding',
distance_type => 'EUCLIDEAN',
-- Only neighbors with distance < max_distance are returned.
max_distance => 0.6
);
/*----------+-------------------+----------------------+---------------+----------------------+
| query_id | query_description | title | artist | distance |
+----------+-------------------+----------------------+---------------+----------------------+
| queryA | Folk Rock | Hallelujah | Leonard Cohen | 0.17320508075688773 |
| queryA | Folk Rock | So What | Miles Davis | 0.5385164807134505 |
| queryA | Folk Rock | Like a Rolling Stone | Bob Dylan | 0.5744562646538029 |
+----------+-------------------+----------------------+---------------+----------------------*/
The following example searches the song_embedding column of the Songs base
table for embeddings that are within a DOT_PRODUCT maximum distance of -0.8
for each row in the QuerySimilarSongs query table.
SELECT
query.query_id,
query.description AS query_description,
base.title,
base.artist,
distance -- Negative dot product value
FROM VECTOR_SEARCH(
TABLE Songs,
'song_embedding',
TABLE QuerySimilarSongs,
query_column_to_search => 'search_embedding',
distance_type => 'DOT_PRODUCT',
max_distance => -0.8 -- Equivalent to DOT_PRODUCT > 0.8
);
/*----------+-------------------+------------------------+-----------------+----------+
| query_id | query_description | title | artist | distance |
+----------+-------------------+------------------------+-----------------+----------+
| queryA | Folk Rock | So What | Miles Davis | -0.94 |
| queryA | Folk Rock | What a Wonderful World | Louis Armstrong | -0.88 |
| queryB | Mellow Jazz | What a Wonderful World | Louis Armstrong | -0.81 |
+----------+-------------------+------------------------+-----------------+----------*/
In the previous example, DOT_PRODUCT > -max_distance. Remember that when
max_distance is used with a DOT_PRODUCT distance type, the max_distance
must be equivalent to -1 * DOT_PRODUCT. The previous example follows the logic
DOT_PRODUCT > -max_distance, which is equivalent to the expected logic -1 *
DOT_PRODUCT < max_distance.