<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>article How to perform Semantic Search in Databricks Lakebase in Lakebase Blogs</title>
    <link>https://community.databricks.com/t5/lakebase-blogs/how-to-perform-semantic-search-in-databricks-lakebase/ba-p/139846</link>
    <description>&lt;H1&gt;&lt;SPAN&gt;Introduction&lt;/SPAN&gt;&lt;/H1&gt;
&lt;P&gt;&lt;SPAN&gt;In today’s AI-native world, applications no longer rely on exact keyword matches—they understand meaning. This shift is powered by &lt;/SPAN&gt;&lt;STRONG&gt;embeddings&lt;/STRONG&gt;&lt;SPAN&gt;: numerical representations of text that capture semantic similarity. For instance, a user searching for &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“moisturizer for dry skin”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; should also find products titled &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“hydrating face cream”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; or &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“intense moisture lotion”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt;. While the words may differ, their meanings are similar—something traditional keyword search would miss. Embeddings help bridge this gap, enabling &lt;/SPAN&gt;&lt;STRONG&gt;semantic search&lt;/STRONG&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;STRONG&gt;RAG (Retrieval-Augmented Generation)&lt;/STRONG&gt;&lt;SPAN&gt;, and &lt;/SPAN&gt;&lt;STRONG&gt;intelligent recommendations&lt;/STRONG&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;With pgvector— supported on &lt;/SPAN&gt;&lt;A href="https://www.databricks.com/blog/what-is-a-lakebase" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Databricks Lakebase&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; (Postgres OLTP database)—you can store, index, and query embeddings natively in SQL, bringing the power of semantic search directly to your data lakehouse.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H1&gt;&lt;SPAN&gt;Why pgvector on Databricks Lakebase?&lt;/SPAN&gt;&lt;/H1&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Unified Platform&lt;/STRONG&gt;&lt;SPAN&gt;: No separate vector database needed—everything runs in your existing Postgres instance.&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;OLTP + AI&lt;/STRONG&gt;&lt;SPAN&gt;: Store product metadata and embeddings together in a single system.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Lakehouse Integration:&lt;/STRONG&gt; &lt;SPAN&gt;Unity Catalog tables, which are created from OLAP workloads, can be effortlessly mirrored in Lakebase using&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/oltp/instances/sync-data/sync-table" target="_blank" rel="noopener"&gt;Synced tables&lt;/A&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;100% pure Postgres&lt;/STRONG&gt;&lt;SPAN&gt;: Works elegantly with psycopg, JDBC, and your favorite BI tools&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Scalable Performance&lt;/STRONG&gt;&lt;SPAN&gt;: IVFFlat and HNSW indexes enable fast vector search at scale&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Unity Catalog Integration:&lt;/STRONG&gt;&lt;SPAN&gt; Register a Postgres Database as a Catalog in UC. Data can be queried through DBSQL using query federation.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;This blog explores Postgres' native search features, specifically full-text search (keyword matching) and vector-based search (text embeddings), as an alternative to Databricks' managed &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/generative-ai/vector-search" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Mosaic AI Vector Search&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;. While Mosaic AI Vector Search currently offers closer integration with Unity Catalog, this guide focuses on leveraging Postgres' capabilities. The choice between Mosaic AI Vector Search and Postgres' native search depends on your specific use case.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H1&gt;&lt;SPAN&gt;Semantic Search in Real-World&lt;/SPAN&gt;&lt;/H1&gt;
&lt;H2&gt;&lt;SPAN&gt;E-commerce Product Search&lt;/SPAN&gt;&lt;/H2&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Semantic Product Discovery&lt;/STRONG&gt;&lt;SPAN&gt;: Find products even when customers use different terminology. For example, a user searches for &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“comfy winter boots for icy sidewalks,”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; and the search returns &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;insulated, slip-resistant boots&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; even if the product titles only say &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“snow boots with rubber sole.”&lt;/SPAN&gt;&lt;/I&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Recommendation Systems&lt;/STRONG&gt;&lt;SPAN&gt;: Identify similar products based on embeddings. For example, a prospect views a &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“14-inch lightweight business laptop,”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; and the site recommends similar ultrabooks from other brands based on semantic similarity of specs and reviews, not just matching &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“14-inch”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; in the title.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Search Analytics&lt;/STRONG&gt;&lt;SPAN&gt;: Understand what customers are looking for through query analysis. By clustering semantically similar queries like &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“work from home chair,”&lt;/SPAN&gt;&lt;/I&gt; &lt;I&gt;&lt;SPAN&gt;“ergonomic office seat,”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“chair for back pain,”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; the retailer sees a strong demand for ergonomic chairs and decides to expand that category.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;&lt;SPAN&gt;Content Management&lt;/SPAN&gt;&lt;/H2&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Document Search&lt;/STRONG&gt;&lt;SPAN&gt;: Find relevant documents based on meaning, not just keywords. To fulfil a GDPR compliance requirement, an employee searches &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“how do we handle customer data deletion requests,”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; and the system surfaces the &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“Data Subject Rights Handling Procedure”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; PDF even though it never uses the exact phrase “deletion requests.”&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Knowledge Base&lt;/STRONG&gt;&lt;SPAN&gt;: Power intelligent FAQ systems and help desk solutions. For example, a business traveller asks, &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“Can I use this app when I’m offline on a flight?”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; and the help center returns the article &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“Using the mobile app without an internet connection,”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; even though the query never mentions &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“mobile app”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; or &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“offline mode”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; explicitly.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Content Recommendations&lt;/STRONG&gt;&lt;SPAN&gt;: Suggest related articles or resources. After reading an article called &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“How to Save Money on Groceries,”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; the site recommends other posts like &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“Beginner’s Guide to Budgeting”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“Easy Cheap Dinner Recipes,”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; because they’re about similar ideas (saving money), even if they don’t share the same words.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;&lt;SPAN&gt;Customer Support&lt;/SPAN&gt;&lt;/H2&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Ticket Classification&lt;/STRONG&gt;&lt;SPAN&gt;: Automatically categorize support tickets using semantic similarity. Tickets like &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“charged twice on my card,” “duplicate payment on statement,” &lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt;and&lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt; “double billing issue” &lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt;are all routed to the “Billing &amp;gt; Duplicate Charges” queue automatically.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Answer Retrieval&lt;/STRONG&gt;&lt;SPAN&gt;: Find relevant answers from knowledge bases. A support agent types &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“customer wants to change shipping address after ordering”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; into their console, and the system surfaces the internal SOP &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“Post-order address change policy”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; as the top suggested reply.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Sentiment Analysis&lt;/STRONG&gt;&lt;SPAN&gt;: Combine with other AI models for comprehensive customer insights. Support messages like “&lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;app keeps crashing,&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt;” &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“can’t open the app,”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;“screen freezes all the time”&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; get grouped together, and sentiment analysis shows most of them are very angry or frustrated—signaling there’s a serious new bug the team needs to fix quickly.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;The subsequent steps will familiarize you with Postgres' search functionalities. You will learn to search for products like "All Beauty" using semantically rich phrases such as "sun protection for sensitive skin" or "hydration booster for face."&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H1&gt;&lt;SPAN&gt;Architecture Overview&lt;/SPAN&gt;&lt;/H1&gt;
&lt;P&gt;&lt;SPAN&gt;Our semantic search solution follows this workflow:&lt;/SPAN&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Data Ingestion and Enrichment&lt;/STRONG&gt;&lt;SPAN&gt;: Load product data from external sources (e.g., Amazon product metadata). Create searchable text and generate embeddings using &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/large-language-models/ai-functions" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Databricks AI functions&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Synced Tables&lt;/STRONG&gt;&lt;SPAN&gt;: Sync enriched data to Postgres via Lakehouse Federation&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Search Optimization&lt;/STRONG&gt;&lt;SPAN&gt;: Create search-optimized tables with both full-text and vector indexes&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Query Execution&lt;/STRONG&gt;&lt;SPAN&gt;: Perform hybrid (full-text and vector-based) searches combining semantic and keyword matching&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P class="lia-align-center"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="uday_satapathy_0-1763668095320.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21856iCFE2B899012CDBD6/image-size/large?v=v2&amp;amp;px=999" role="button" title="uday_satapathy_0-1763668095320.png" alt="uday_satapathy_0-1763668095320.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Step 1: Data Ingestion and Enrichment in Databricks&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;We'll start by loading Amazon product metadata for the category &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;‘All Beauty’&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; from the &lt;/SPAN&gt;&lt;A href="https://amazon-reviews-2023.github.io/" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Amazon Reviews 2023 dataset&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; and enriching it with searchable text and embeddings.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;Setting Up the Environment&lt;/SPAN&gt;&lt;/H3&gt;
&lt;LI-CODE lang="markup"&gt;CREATE CATALOG IF NOT EXISTS amazon_reviews_23;
CREATE SCHEMA IF NOT EXISTS amazon_reviews_23.datasets;
CREATE VOLUME IF NOT EXISTS amazon_reviews_23.datasets.raw;
&lt;/LI-CODE&gt;
&lt;H3&gt;&lt;SPAN&gt;Loading and Processing Data&lt;/SPAN&gt;&lt;/H3&gt;
&lt;LI-CODE lang="python"&gt;from pyspark.sql.functions import from_json, schema_of_json, col, lit, expr, concat_ws
import requests

# Download Amazon Beauty product metadata
all_beauty_prod_meta_link = "https://mcauleylab.ucsd.edu/public_datasets/data/amazon_2023/raw/meta_categories/meta_All_Beauty.jsonl.gz"
uc_volume_path = "/Volumes/amazon_reviews_23/datasets/raw/meta_All_Beauty.jsonl.gz"

response = requests.get(all_beauty_prod_meta_link, stream=True)
response.raise_for_status()

with open(uc_volume_path, "wb") as f:
    for chunk in response.iter_content(chunk_size=8192):
        if chunk:
            f.write(chunk)&lt;/LI-CODE&gt;
&lt;H3&gt;&lt;SPAN&gt;Data Transformation and Enrichment&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;We clean the Amazon Reviews 2023 dataset by removing duplicate columns and invalid characters from column names. Then, we create a &lt;/SPAN&gt;&lt;SPAN&gt;search_text&lt;/SPAN&gt;&lt;SPAN&gt; column that consolidates all relevant textual information for product searches.&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;def flatten_and_sanitize(df, parent=""):
    """Clean up column names and flatten nested structs in the input dataframe"""
    fields = []
    for field in df.schema.fields:
        name = f"{parent}.{field.name}" if parent else field.name
        clean_name = name.replace(" ", "_").replace(".", "_").replace(",", "_") \
                          .replace(";", "_").replace("{", "_").replace("}", "_") \
                          .replace("(", "_").replace(")", "_").replace("\n", "_") \
                          .replace("\t", "_").replace("=", "_")
        if str(field.dataType).startswith("StructType"):
            fields += flatten_and_sanitize(df.select(col(field.name + ".*")), parent=clean_name)
        else:
            fields.append(col(name).alias(clean_name))
    return fields

def prepare_for_search(df):
    """Generate a search text column and embedding column from the input dataframe"""
    df = df.withColumn(
        "search_text",
        concat_ws(
            " ",
            "parent_asin",
            "title",
            "main_category",
            expr("array_join(categories, ' ')"),
            expr("array_join(description, ' ')"),
            expr("array_join(features, ' ')"),
            "store",
            "details_UPC",
            "details_Package_Dimensions"
        )
    )
    df = df.withColumn(
        "embedding",
        expr("ai_query('databricks-gte-large-en', search_text)")
    )
    return df

# Process the raw data
raw_df = spark.read.text(uc_volume_path)
sample_json = raw_df.limit(1).collect()[0][0]
json_schema = schema_of_json(sample_json)

parsed_df = raw_df.select(
    from_json("value", json_schema).alias("data")
).select("data.*")

flat_df = (parsed_df.select(flatten_and_sanitize(parsed_df))
           .transform(prepare_for_search)
           )

# Save the enriched data
flat_df.write.mode("overwrite").saveAsTable(
    "amazon_reviews_23.datasets.meta_all_beauty"
)
&lt;/LI-CODE&gt;
&lt;H3&gt;&lt;SPAN&gt;Key Features of the Data Processing&lt;/SPAN&gt;&lt;/H3&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Schema Flattening&lt;/STRONG&gt;&lt;SPAN&gt;: Automatically handles nested JSON structures and sanitizes column names&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Search Text Generation&lt;/STRONG&gt;&lt;SPAN&gt;: Combines multiple fields (title, categories, description, features) into a single searchable text field&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Embedding Generation&lt;/STRONG&gt;&lt;SPAN&gt;: Uses Databricks' built-in &lt;/SPAN&gt;&lt;SPAN&gt;ai_query&lt;/SPAN&gt;&lt;SPAN&gt; function with the &lt;/SPAN&gt;&lt;FONT face="courier new,courier"&gt;&lt;SPAN&gt;databricks-gte-large-en&lt;/SPAN&gt;&lt;/FONT&gt;&lt;SPAN&gt; model to generate 1024-dimensional embeddings&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Data Quality&lt;/STRONG&gt;&lt;SPAN&gt;: Handles missing values and ensures consistent data types&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;&lt;SPAN&gt;Step 2: Load the table into Lakebase&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;We now possess the &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;meta_all_beauty&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; Unity Catalog table. However, for transactional applications, product searches against this dataset would typically occur within an OLTP database. This is where Databricks Lakebase becomes essential.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;As a prerequisite, you can follow these steps to &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/oltp/instances/create/" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;create a lakebase instance&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/oltp/instances/register-uc" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;register this database as a catalog in UC&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;. We will take the next few steps to load the data in &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;meta_all_beauty&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; into our Postgres database using the concept of &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/oltp/instances/sync-data/sync-table" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Synced tables&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;. Synced Tables offer a ‘managed data synchronization’ service from Unity Catalog tables to Postgres tables.&lt;/SPAN&gt;&lt;SPAN&gt; You can decide ‘how’, and ‘how frequently’, the data replication happens by choosing one of the following modes:&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Snapshot&lt;/STRONG&gt;&lt;SPAN&gt; – Replaces the entire destination with a fresh full copy of the source table on each run; most efficient for large changes.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Triggered&lt;/STRONG&gt;&lt;SPAN&gt; – Copies only incremental changes since the last run when manually or programmatically triggered; balances cost and lag.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Continuous&lt;/STRONG&gt;&lt;SPAN&gt; – Continuously streams changes from the source to the destination in near real time; lowest lag but highest cost.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;&lt;SPAN&gt;Various phases of a Synced table - Creation, Provisioning and Online Stages&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Please note that the UI may change as the product evolves.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H4&gt;&lt;SPAN&gt;Creation of a Synced Table&lt;/SPAN&gt;&lt;/H4&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="uday_satapathy_1-1763668485591.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21857iEC1B58D52C4343CB/image-size/large?v=v2&amp;amp;px=999" role="button" title="uday_satapathy_1-1763668485591.png" alt="uday_satapathy_1-1763668485591.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H4&gt;&lt;SPAN&gt;Sync begins&lt;/SPAN&gt;&lt;/H4&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="uday_satapathy_2-1763668485591.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21858i895C1D6979688C23/image-size/large?v=v2&amp;amp;px=999" role="button" title="uday_satapathy_2-1763668485591.png" alt="uday_satapathy_2-1763668485591.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H4&gt;&lt;SPAN&gt;Rows being copied&lt;/SPAN&gt;&lt;/H4&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="uday_satapathy_3-1763668485592.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21859i26AA6A81F522409F/image-size/large?v=v2&amp;amp;px=999" role="button" title="uday_satapathy_3-1763668485592.png" alt="uday_satapathy_3-1763668485592.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H4&gt;&lt;SPAN&gt;Sync finished and the Postgres target table is online&lt;/SPAN&gt;&lt;/H4&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="uday_satapathy_4-1763668485592.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21860iEFAF95E9548D930F/image-size/large?v=v2&amp;amp;px=999" role="button" title="uday_satapathy_4-1763668485592.png" alt="uday_satapathy_4-1763668485592.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H4&gt;&lt;SPAN&gt;Querying the Synced table from the Postgres SQL Editor:&lt;/SPAN&gt;&lt;/H4&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="uday_satapathy_5-1763668485593.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21861i7DB3B44783C5E068/image-size/large?v=v2&amp;amp;px=999" role="button" title="uday_satapathy_5-1763668485593.png" alt="uday_satapathy_5-1763668485593.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H4&gt;&lt;SPAN&gt;The DDL for this Synced table in Postgres looks like this:&lt;/SPAN&gt;&lt;/H4&gt;
&lt;LI-CODE lang="python"&gt;CREATE TABLE product_reviews_analysis_oltp.meta_all_beauty (
	average_rating float8 NULL,
	bought_together text NULL,
	categories jsonb NULL,
	description jsonb NULL,
	"details_Package_Dimensions" text NULL,
	"details_UPC" text NULL,
	features jsonb NULL,
	images jsonb NULL,
	main_category text NOT NULL,
	parent_asin text NOT NULL,
	price text NULL,
	rating_number int8 NULL,
	store text NULL,
	title text NULL,
	videos jsonb NULL,
	search_text text NULL,
	embedding jsonb NULL,
	CONSTRAINT meta_all_beauty_pkey PRIMARY KEY (parent_asin, main_category)
)
PARTITION BY RANGE (parent_asin, main_category);&lt;/LI-CODE&gt;
&lt;H2&gt;&lt;SPAN&gt;Step 3: Postgres Setup for Search&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;Now we'll set up the Postgres side with pgvector support and create our search-optimized tables.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;Enable pgvector Extension&lt;/SPAN&gt;&lt;/H3&gt;
&lt;LI-CODE lang="markup"&gt;CREATE EXTENSION IF NOT EXISTS vector;&lt;/LI-CODE&gt;
&lt;H3&gt;&lt;SPAN&gt;Create the Search-Optimized Table&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Product searches will happen against the &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;meta_all_beauty_indexed&lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt; table. This table is built using the data from the &lt;/SPAN&gt;&lt;I&gt;&lt;SPAN&gt;meta_all_beauty &lt;/SPAN&gt;&lt;/I&gt;&lt;SPAN&gt;table (synced table) after adding two columns carrying indexing information for search. These columns are:&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;embedding_pg::VECTOR(1024): Column with PGVector datatype to house embeddings for text.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;search_vector::TSVECTOR: Column with Text Search datatype, optimized for full text search.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;LI-CODE lang="markup"&gt;CREATE TABLE product_reviews_analysis_oltp.meta_all_beauty_indexed (
  parent_asin TEXT NOT NULL,
  main_category TEXT NOT NULL,
  search_text TEXT NOT NULL,
  embedding_pg VECTOR(1024),
  search_vector TSVECTOR,
  PRIMARY KEY (parent_asin, main_category)
);
&lt;/LI-CODE&gt;
&lt;H3&gt;&lt;SPAN&gt;Populate the Table with Data&lt;/SPAN&gt;&lt;/H3&gt;
&lt;LI-CODE lang="markup"&gt;INSERT INTO product_reviews_analysis_oltp.meta_all_beauty_indexed (
  parent_asin, main_category, search_text, search_vector, embedding_pg
)
SELECT
  parent_asin,
  main_category,
  search_text,
  to_tsvector('english', search_text),
  string_to_array(trim(both '[]' from embedding::text), ',')::float8[]::vector
FROM product_reviews_analysis_oltp.meta_all_beauty;
&lt;/LI-CODE&gt;
&lt;P&gt;&lt;SPAN&gt;In case the synced table is refreshed incrementally (Continuous / Triggered Mode) and the amount of inserts / updates happening in each refresh is much lower than the prior amount of data in the synced table, you could use a ‘merge’ operation (which happens in Postgres through an INSERT + ON CONFLICT pattern) to refresh the search index table. You could add a last_modified_date column in the source tables. For a given primary key, if the incoming row has a last_modified_date greater than that of the existing row, perform an update operation instead of an insert:&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;INSERT INTO product_reviews_analysis_oltp.meta_all_beauty_indexed (
  parent_asin,
  main_category,
  search_text,
  search_vector,
  embedding_pg,
  last_modified
)
SELECT
  parent_asin,
  main_category,
  search_text,
  to_tsvector('english', search_text),
  string_to_array(trim(both '[]' from embedding::text), ',')::float8[]::vector,
  last_modified
FROM product_reviews_analysis_oltp.meta_all_beauty
WHERE embedding IS NOT NULL  -- optional safeguard
ON CONFLICT (parent_asin, main_category)
DO UPDATE SET
  search_text = EXCLUDED.search_text,
  search_vector = EXCLUDED.search_vector,
  embedding_pg = EXCLUDED.embedding_pg,
  last_modified = EXCLUDED.last_modified
WHERE EXCLUDED.last_modified &amp;gt; product_reviews_analysis_oltp.meta_all_beauty_indexed.last_modified;&lt;/LI-CODE&gt;
&lt;H3&gt;&lt;SPAN&gt;Create Optimized Indexes&lt;/SPAN&gt;&lt;/H3&gt;
&lt;LI-CODE lang="markup"&gt;-- Full-text search index
CREATE INDEX idx_beauty_fts
  ON product_reviews_analysis_oltp.meta_all_beauty_indexed
  USING GIN (search_vector);

-- Vector similarity search index
CREATE INDEX idx_beauty_vector
  ON product_reviews_analysis_oltp.meta_all_beauty_indexed
  USING ivfflat (embedding_pg vector_cosine_ops)
  WITH (lists = 100);

-- Update table statistics
ANALYZE product_reviews_analysis_oltp.meta_all_beauty_indexed;&lt;/LI-CODE&gt;
&lt;H3&gt;&lt;SPAN&gt;Understanding the Index Types&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Before diving into the queries, let's understand what these indexes do:&lt;/SPAN&gt;&lt;/P&gt;
&lt;H4&gt;&lt;SPAN&gt;GIN (Generalized Inverted Index)&lt;/SPAN&gt;&lt;/H4&gt;
&lt;P&gt;&lt;SPAN&gt;Think of GIN as a &lt;/SPAN&gt;&lt;STRONG&gt;book's index&lt;/STRONG&gt;&lt;SPAN&gt; but for text search. When you search for "vitamin C serum," GIN quickly finds all documents containing those words without scanning every single record. It's like having a smart librarian who knows exactly which pages contain your search terms.&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Best for&lt;/STRONG&gt;&lt;SPAN&gt;: Full-text search, exact word matches&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Speed&lt;/STRONG&gt;&lt;SPAN&gt;: Very fast for keyword searches&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Memory&lt;/STRONG&gt;&lt;SPAN&gt;: Moderate memory usage&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Example&lt;/STRONG&gt;&lt;SPAN&gt;: Finding all products that contain "moisturizer" or "anti-aging"&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H4&gt;&lt;SPAN&gt;IVFFlat (Inverted File with Flat Compression)&lt;/SPAN&gt;&lt;/H4&gt;
&lt;P&gt;&lt;SPAN&gt;Imagine you have 1 million product descriptions, and you want to find the 10 most similar ones to a query. IVFFlat is like organizing products into &lt;/SPAN&gt;&lt;STRONG&gt;100 different buckets&lt;/STRONG&gt;&lt;SPAN&gt; based on their similarity. When you search, it only looks in the most relevant buckets instead of checking all 1 million products.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="uday_satapathy_6-1763668863979.png" style="width: 716px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21863i4D5BD5481858F01B/image-dimensions/716x478?v=v2" width="716" height="478" role="button" title="uday_satapathy_6-1763668863979.png" alt="uday_satapathy_6-1763668863979.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Best for&lt;/STRONG&gt;&lt;SPAN&gt;: Vector similarity search, finding "similar" items&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Speed&lt;/STRONG&gt;&lt;SPAN&gt;: Fast for approximate similarity search&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Memory&lt;/STRONG&gt;&lt;SPAN&gt;: Low memory usage&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Build time:&lt;/STRONG&gt;&lt;SPAN&gt; Faster index build time than HNSW.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Rebuild time upon incremental updates:&lt;/STRONG&gt;&lt;SPAN&gt; Generally, a full-rebuild is needed (slow).&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Example&lt;/STRONG&gt;&lt;SPAN&gt;: Finding products similar to "vitamin C serum" even if they don't contain those exact words&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H4&gt;&lt;SPAN&gt;HNSW (Hierarchical Navigable Small World)&lt;/SPAN&gt;&lt;/H4&gt;
&lt;P&gt;&lt;SPAN&gt;HNSW is like having a &lt;/SPAN&gt;&lt;STRONG&gt;smart GPS for similarity search&lt;/STRONG&gt;&lt;SPAN&gt;. Instead of checking every possible route, it uses a network of connections to quickly navigate to the most similar items. It's more sophisticated than IVFFlat and often faster, but uses more memory. &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/generative-ai/vector-search" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Mosaic AI Vector Search&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; uses HNSW indexing.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="uday_satapathy_7-1763668863976.png" style="width: 602px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21862i084FB82D9F9E2327/image-dimensions/602x902?v=v2" width="602" height="902" role="button" title="uday_satapathy_7-1763668863976.png" alt="uday_satapathy_7-1763668863976.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Best for&lt;/STRONG&gt;&lt;SPAN&gt;: High-performance vector similarity search&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Speed&lt;/STRONG&gt;&lt;SPAN&gt;: Very fast, often faster than IVFFlat&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Memory&lt;/STRONG&gt;&lt;SPAN&gt;: Higher memory usage&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Build time:&lt;/STRONG&gt;&lt;SPAN&gt; Slower index build time than IVFFlat.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Rebuild time upon incremental updates:&lt;/STRONG&gt;&lt;SPAN&gt; Fast insert into a graph. No global rebuild needed.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Example&lt;/STRONG&gt;&lt;SPAN&gt;: Finding the most similar products in a large catalog with sub-second response times&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H4&gt;&lt;SPAN&gt;When to Use Each Index&lt;/SPAN&gt;&lt;/H4&gt;
&lt;TABLE&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P&gt;&lt;STRONG&gt;Index Type&lt;/STRONG&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;STRONG&gt;Use Case&lt;/STRONG&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;STRONG&gt;Speed&lt;/STRONG&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;STRONG&gt;Memory&lt;/STRONG&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;STRONG&gt;Best For&lt;/STRONG&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P&gt;&lt;STRONG&gt;GIN&lt;/STRONG&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;Text search&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;Very Fast&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;Low&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;"Find products with 'vitamin C'"&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P&gt;&lt;STRONG&gt;IVFFlat&lt;/STRONG&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;Vector similarity&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;Fast&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;Low&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;"Find products similar to this one"&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P&gt;&lt;STRONG&gt;HNSW&lt;/STRONG&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;Vector similarity&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;Very Fast&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;High&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;TD&gt;
&lt;P&gt;&lt;SPAN&gt;"Find similar products in huge catalogs"&lt;/SPAN&gt;&lt;/P&gt;
&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&lt;SPAN&gt;For most applications, start with GIN for text search and IVFFlat for vector search. Upgrade to HNSW when you need maximum performance and have sufficient memory.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Step 4: Search Query Examples&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;Now let's explore different types of search queries you can perform.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;Full-Text Search Only&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Perfect for exact keyword matches and traditional search functionality:&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;WITH fts_search AS (
  SELECT parent_asin, main_category
  FROM product_reviews_analysis_oltp.meta_all_beauty_indexed
  WHERE search_vector @@ plainto_tsquery('english', 'vitamin c moisturizer')
  LIMIT 10
)
SELECT
  f.parent_asin,
  f.main_category,
  m.title,
  m.price,
  m.rating_number,
  m.categories
FROM fts_search f
JOIN product_reviews_analysis_oltp.meta_all_beauty m
  ON f.parent_asin = m.parent_asin AND f.main_category = m.main_category;&lt;/LI-CODE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="uday_satapathy_8-1763669333108.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21864i792A910C27B1326C/image-size/large?v=v2&amp;amp;px=999" role="button" title="uday_satapathy_8-1763669333108.png" alt="uday_satapathy_8-1763669333108.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;Ranked Full-Text Search&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Enhance your search results with relevance scoring. The &lt;/SPAN&gt;&lt;SPAN&gt;ts_rank_cd()&lt;/SPAN&gt;&lt;SPAN&gt; function computes a &lt;/SPAN&gt;&lt;STRONG&gt;ranking score&lt;/STRONG&gt;&lt;SPAN&gt; indicating the degree to which the &lt;/SPAN&gt;&lt;SPAN&gt;search_vector&lt;/SPAN&gt;&lt;SPAN&gt; column aligns with the query 'vitamin c serum'. The &lt;/SPAN&gt;&lt;SPAN&gt;@@&lt;/SPAN&gt;&lt;SPAN&gt; operator determines (as a boolean) if a &lt;/SPAN&gt;&lt;SPAN&gt;tsvector&lt;/SPAN&gt;&lt;SPAN&gt; matches a &lt;/SPAN&gt;&lt;SPAN&gt;tsquery&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;WITH fts_ranked AS (
  SELECT
    parent_asin,
    main_category,
    ts_rank_cd(search_vector, plainto_tsquery('english', 'vitamin c serum')) AS rank
  FROM product_reviews_analysis_oltp.meta_all_beauty_indexed
  WHERE search_vector @@ plainto_tsquery('english', 'vitamin c serum')
  ORDER BY rank DESC
  LIMIT 10
)
SELECT
  r.parent_asin,
  r.main_category,
  m.title,
  m.average_rating,
  m.price,
  r.rank
FROM fts_ranked r
JOIN product_reviews_analysis_oltp.meta_all_beauty m
  ON r.parent_asin = m.parent_asin AND r.main_category = m.main_category;&lt;/LI-CODE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="uday_satapathy_9-1763669526405.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21865iAAE116B723E0277A/image-size/large?v=v2&amp;amp;px=999" role="button" title="uday_satapathy_9-1763669526405.png" alt="uday_satapathy_9-1763669526405.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;Vector Similarity Search&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;To find semantically similar products, you generate vector embeddings for your search text using the same embedding model that created the vector index. You then query the index to retrieve documents most similar to these generated embeddings. We achieve this by utilizing &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/aws/en/machine-learning/model-serving/query-embedding-models?language=SQL" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Databricks' &lt;/SPAN&gt;&lt;SPAN&gt;ai_query()&lt;/SPAN&gt;&lt;SPAN&gt; function with the &lt;/SPAN&gt;&lt;SPAN&gt;databricks-gte-large-en&lt;/SPAN&gt;&lt;SPAN&gt; foundation model&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; to generate the embeddings.&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;WITH vector_search AS (
  SELECT parent_asin, main_category
  FROM product_reviews_analysis_oltp.meta_all_beauty_indexed
  ORDER BY embedding_pg &amp;lt;-&amp;gt; '[0.3544921875,-0.272705078125,...]'::vector
  LIMIT 10
)
SELECT
  v.parent_asin,
  v.main_category,
  m.title,
  m.price,
  m.average_rating,
  m.store
FROM vector_search v
JOIN product_reviews_analysis_oltp.meta_all_beauty m
  ON v.parent_asin = m.parent_asin AND v.main_category = m.main_category;&lt;/LI-CODE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="uday_satapathy_10-1763669606900.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21866iB56EA47CC164B480/image-size/large?v=v2&amp;amp;px=999" role="button" title="uday_satapathy_10-1763669606900.png" alt="uday_satapathy_10-1763669606900.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;Hybrid Search&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Combine the power of both full-text and vector search for the best results:&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;WITH search_results AS (
  SELECT parent_asin, main_category
  FROM product_reviews_analysis_oltp.meta_all_beauty_indexed
  WHERE search_vector @@ plainto_tsquery('english', 'vitamin c moisturizer')
  ORDER BY embedding_pg &amp;lt;-&amp;gt; '[0.3544921875,-0.272705078125,...]'::vector
  LIMIT 10
)
SELECT
  r.parent_asin,
  r.main_category,
  m.title,
  m.store,
  m.average_rating,
  m.rating_number,
  m.price,
  m.categories,
  m.features,
  m.description
FROM search_results r
JOIN product_reviews_analysis_oltp.meta_all_beauty m
  ON r.parent_asin = m.parent_asin AND r.main_category = m.main_category;&lt;/LI-CODE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="uday_satapathy_11-1763669654141.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/21867i53DA488CC2AAEFFD/image-size/large?v=v2&amp;amp;px=999" role="button" title="uday_satapathy_11-1763669654141.png" alt="uday_satapathy_11-1763669654141.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Performance Optimization Tips&lt;/SPAN&gt;&lt;/H2&gt;
&lt;H3&gt;&lt;SPAN&gt;Index Tuning&lt;/SPAN&gt;&lt;/H3&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;IVFFlat Index&lt;/STRONG&gt;&lt;SPAN&gt;: Adjust the &lt;/SPAN&gt;&lt;SPAN&gt;lists&lt;/SPAN&gt;&lt;SPAN&gt; parameter based on your data size. For 1M vectors, use 100-1000 lists&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;HNSW Index&lt;/STRONG&gt;&lt;SPAN&gt;: For even better performance, consider upgrading to HNSW when available&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;GIN Index&lt;/STRONG&gt;&lt;SPAN&gt;: Optimize for your typical query patterns&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;&lt;SPAN&gt;Query Optimization&lt;/SPAN&gt;&lt;/H3&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Use &lt;/SPAN&gt;&lt;SPAN&gt;LIMIT&lt;/SPAN&gt;&lt;SPAN&gt; clauses to control result set size&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Combine filters to reduce the search space before vector operations&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Consider using approximate search for very large datasets&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;&lt;SPAN&gt;Monitoring and Maintenance&lt;/SPAN&gt;&lt;/H3&gt;
&lt;LI-CODE lang="markup"&gt;-- Check index usage
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
WHERE tablename = 'meta_all_beauty_indexed';

-- Monitor query performance
EXPLAIN (ANALYZE, BUFFERS) 
SELECT * FROM product_reviews_analysis_oltp.meta_all_beauty_indexed
WHERE search_vector @@ plainto_tsquery('english', 'vitamin c');
&lt;/LI-CODE&gt;
&lt;H2&gt;&lt;SPAN&gt;Best Practices&lt;/SPAN&gt;&lt;/H2&gt;
&lt;H3&gt;&lt;SPAN&gt;Data Quality&lt;/SPAN&gt;&lt;/H3&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Consistent Text Processing&lt;/STRONG&gt;&lt;SPAN&gt;: Ensure your search text generation is consistent across all records&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Embedding Quality&lt;/STRONG&gt;&lt;SPAN&gt;: Use high-quality embedding models and validate results&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Regular Updates&lt;/STRONG&gt;&lt;SPAN&gt;: Keep embeddings current as your data changes&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;&lt;SPAN&gt;Security and Privacy&lt;/SPAN&gt;&lt;/H3&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Access Control&lt;/STRONG&gt;&lt;SPAN&gt;: Implement proper row-level security for sensitive data&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Data Masking&lt;/STRONG&gt;&lt;SPAN&gt;: Consider masking sensitive information in search results&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Audit Logging&lt;/STRONG&gt;&lt;SPAN&gt;: Track search queries for compliance and analytics&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;&lt;SPAN&gt;Scalability&lt;/SPAN&gt;&lt;/H3&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Partitioning&lt;/STRONG&gt;&lt;SPAN&gt;: Consider partitioning large tables by category or date&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Caching&lt;/STRONG&gt;&lt;SPAN&gt;: Implement query result caching for frequently accessed data&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Load Balancing&lt;/STRONG&gt;&lt;SPAN&gt;: Distribute query load across multiple read replicas&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;&lt;SPAN&gt;Conclusion&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;With pgvector on Databricks Lakebase, you can build powerful semantic search capabilities that understand meaning, not just keywords. This unified approach brings together:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Data Engineering&lt;/STRONG&gt;&lt;SPAN&gt;: Seamless data processing with Spark and Delta Lake&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;AI Integration&lt;/STRONG&gt;&lt;SPAN&gt;: Built-in embedding generation with Databricks AI functions&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;OLTP Performance&lt;/STRONG&gt;&lt;SPAN&gt;: Fast, indexed queries with Postgres compatibility&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Scalability&lt;/STRONG&gt;&lt;SPAN&gt;: Enterprise-grade performance with proper indexing strategies&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;The combination of Databricks' data processing power and pgvector's search capabilities creates a compelling solution for modern AI applications. Whether you're building e-commerce search, content discovery, or intelligent document retrieval, this architecture provides the foundation for sophisticated semantic search at scale.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Start with the examples in this guide, adapt them to your specific use case, and watch as your applications become more intelligent and user-friendly through the power of semantic search.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Additional Resources&lt;/SPAN&gt;&lt;/H2&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;A href="https://github.com/pgvector/pgvector" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;pgvector Documentation&lt;/SPAN&gt;&lt;/A&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;A href="https://docs.databricks.com/aws/en/large-language-models/ai-functions" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Databricks AI Functions&lt;/SPAN&gt;&lt;/A&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;A href="https://www.postgresql.org/docs/current/textsearch.html" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Postgres Full-Text Search&lt;/SPAN&gt;&lt;/A&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;A href="https://docs.databricks.com/aws/en/query-federation/" target="_self"&gt;&lt;SPAN&gt;Databricks Lakehouse Federation&lt;/SPAN&gt;&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;</description>
    <pubDate>Thu, 04 Dec 2025 15:58:00 GMT</pubDate>
    <dc:creator>uday_satapathy</dc:creator>
    <dc:date>2025-12-04T15:58:00Z</dc:date>
    <item>
      <title>How to perform Semantic Search in Databricks Lakebase</title>
      <link>https://community.databricks.com/t5/lakebase-blogs/how-to-perform-semantic-search-in-databricks-lakebase/ba-p/139846</link>
      <description>&lt;P&gt;&lt;SPAN class="appsElementsGenerativeaiAstAnimated"&gt;In today's AI-native world, applications are moving beyond keyword matching to embrace&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN class="appsElementsGenerativeaiAstAnimated"&gt;semantic search&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN class="appsElementsGenerativeaiAstAnimated"&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;powered by embeddings. This blog post explores how to leverage&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN class="appsElementsGenerativeaiAstAnimated"&gt;pgvector on Databricks Lakebase&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN class="appsElementsGenerativeaiAstAnimated"&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;(Postgres OLTP database) to natively store, index, and query these embeddings in SQL. Learn the architecture to unify your product metadata, vector data, and operational workloads in a single, scalable Lakehouse-integrated platform for powerful e-commerce search, intelligent recommendations, and more.&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 04 Dec 2025 15:58:00 GMT</pubDate>
      <guid>https://community.databricks.com/t5/lakebase-blogs/how-to-perform-semantic-search-in-databricks-lakebase/ba-p/139846</guid>
      <dc:creator>uday_satapathy</dc:creator>
      <dc:date>2025-12-04T15:58:00Z</dc:date>
    </item>
    <item>
      <title>Re: How to perform Semantic Search in Databricks Lakebase</title>
      <link>https://community.databricks.com/t5/lakebase-blogs/how-to-perform-semantic-search-in-databricks-lakebase/bc-p/141178#M12</link>
      <description>&lt;P&gt;&lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/82106"&gt;@uday_satapathy&lt;/a&gt;&amp;nbsp;- Quite comprehensive example. Thanks.&lt;/P&gt;</description>
      <pubDate>Thu, 04 Dec 2025 16:10:04 GMT</pubDate>
      <guid>https://community.databricks.com/t5/lakebase-blogs/how-to-perform-semantic-search-in-databricks-lakebase/bc-p/141178#M12</guid>
      <dc:creator>Raman_Unifeye</dc:creator>
      <dc:date>2025-12-04T16:10:04Z</dc:date>
    </item>
  </channel>
</rss>

