The Finvest Finance Advisor demonstrates Cloud Spanner’s multi-modal capabilities for complex financial services workloads. This application showcases how to combine relational data, full-text search, semantic vector search, and graph traversal in a single platform.
Use case: Find funds investing in derivatives across regions
SELECT DISTINCT fund_name, investment_strategy, investment_managers, fund_trailing_return_ytd, top5_holdingsFROM EU_MutualFunds WHERE SEARCH(investment_strategy_Tokens, 'derivatives') ORDER BY fund_name;
How it works:
investment_strategy_Tokens is a token search index on the strategy text
SEARCH() performs full-text matching on tokenized content
Returns exact matches for “derivatives” in investment strategy descriptions
Use case: Find fund manager “Elizabeth Peterson” when searching “Liz Peters”
SELECT DISTINCT fund_name, manager, strategy, score FROM ( SELECT fund_name, investment_managers AS manager, investment_strategy AS strategy, SCORE_NGRAMS( investment_managers_Substring_Tokens_NGRAM, 'Liz Peters' ) AS score FROM EU_MutualFunds WHERE SEARCH_NGRAMS( investment_managers_Substring_Tokens_NGRAM, 'Liz Peters', min_ngrams=>1 ) AND SEARCH(investment_strategy_Tokens, 'derivatives')) ORDER BY score DESC;
How it works:
SEARCH_NGRAMS() finds substring matches using n-gram indexes
Use case: Find “socially responsible” funds (matches ESG without exact keyword)
-- Uses cosine distance for semantic similaritySELECT fund_name, investment_strategy, investment_managers, COSINE_DISTANCE( investment_strategy_Embedding, ( SELECT embeddings.VALUES FROM ML.PREDICT( MODEL EmbeddingsModel, (SELECT 'socially responsible' AS content) ) ) ) AS distanceFROM EU_MutualFundsWHERE investment_strategy_Embedding IS NOT NULL AND search_substring(investment_managers_substring_tokens, 'Liz Peters')ORDER BY distance LIMIT 10;
-- Step 1: Get embedding for semantic searchWITH embedding AS ( SELECT embeddings.VALUES AS vector FROM ML.PREDICT( MODEL EmbeddingsModel, (SELECT 'socially responsible investments' AS content) )),-- Step 2: ANN search for semantic similarityann_results AS ( SELECT NewMFSequence, APPROX_EUCLIDEAN_DISTANCE( investment_strategy_Embedding_vector, (SELECT vector FROM embedding), options => JSON '{"num_leaves_to_search": 10}' ) AS distance FROM EU_MutualFunds @{force_index = InvestmentStrategyEmbeddingIndex} WHERE investment_strategy_Embedding_vector IS NOT NULL ORDER BY distance LIMIT 500)-- Step 3: Join with full-text and fuzzy filtersSELECT funds.fund_name, funds.investment_strategy, funds.investment_managersFROM ann_results AS annJOIN EU_MutualFunds AS funds ON ann.NewMFSequence = funds.NewMFSequenceWHERE SEARCH_NGRAMS( funds.investment_managers_Substring_Tokens_NGRAM, 'Liz Peters', min_ngrams=>1)ORDER BY SCORE_NGRAMS( funds.investment_managers_Substring_Tokens_NGRAM, 'Liz Peters') DESC;
-- Update existing rows with embeddingsUPDATE EU_MutualFundsSET investment_strategy_Embedding = ( SELECT embeddings.VALUES FROM ML.PREDICT( MODEL EmbeddingsModel, (SELECT investment_strategy AS content) ))WHERE investment_strategy IS NOT NULL;
-- Create ANN index for fast vector searchCREATE VECTOR INDEX InvestmentStrategyEmbeddingIndexON EU_MutualFunds(investment_strategy_Embedding_vector)WHERE investment_strategy_Embedding_vector IS NOT NULLOPTIONS ( distance_type = 'EUCLIDEAN', num_leaves = 100);
This creates the database with schema and sample data.
3
Configure ML Model
Edit Schema-Operations.sql with your project/region:
ALTER MODEL EmbeddingsModel SET OPTIONS ( endpoint = '//aiplatform.googleapis.com/projects/YOUR_PROJECT_ID/locations/YOUR_REGION/publishers/google/models/text-embedding-005');
Execute in Spanner console.
4
Run Remaining DDL
Execute the rest of Schema-Operations.sql to create: