Vector search optimization: flatten your JSON before embedding

Vector search optimization starts well before the database. Somehow the standard advice in the RAG (Retrieval-Augmented Generation) space became dumping raw JSON into an embedding model, and I keep finding it in WordPress AI integrations. It is a lazy architectural choice, and it is what is holding your retrieval performance back.

After 14 years inside WordPress data structures, the thing I keep coming back to is that machines and humans read differently. Feed a BERT-based model a raw JSON string and you are not handing it structured data, you are handing it noise. That alone can cost you up to 20% of your retrieval quality.

The tokenization trap: noise versus signal

Modern embedding models tokenize with WordPiece or Byte-Pair Encoding (BPE), and both are tuned for natural language: prose, conversation, documentation. When a tokenizer hits a JSON object it does not see a key-value pair. It sees a run of double quotes, colons, braces, and commas.

In any vector search optimization work you want every token carrying semantic weight. Raw JSON spends a large slice of the token budget on structural syntax instead, so the attention mechanism goes to work on the relationship between a curly brace and a colon rather than on the product description.

On a custom WooCommerce search project last year, the first dev on it ran wp_json_encode($product_data) and shipped. The results were garbage, because the sheer frequency of structural tokens pulled the vector away from the semantic center of the text.

The naive approach

// Don't do this. You're embedding syntax, not meaning.
$product_data = [
    'id' => 123,
    'title' => 'Vintage Leather Boots',
    'price' => 150,
    'currency' => 'USD',
    'stock' => 'in_stock'
];

$bad_embedding_input = wp_json_encode( $product_data );
// Result: {"id":123,"title":"Vintage Leather Boots","price":150...}

Why mean pooling makes it worse

Most embedding models build their vector with mean pooling: they average all the token vectors in the document to get a centroid. If a quarter of your tokens are quotes and braces, that centroid is mathematically noisy.

So when someone types a natural query like “What are the best leather boots for winter?”, the distance between that clean query vector and your noisy JSON vector grows. That is the main reason recall is poor in RAG systems. You are asking the engine to compare a sentence with a spreadsheet snippet.

If you are already living with bad results, I wrote about why your RAG system needs a refactor before you sink more hours into it.

The fix: flatten into plain prose

Convert the structured data into something the model was actually trained to read. I do it with a prose template.

Instead of a JSON blob you get a descriptive sentence. That usually cuts the token count by 15 to 20% and raises the semantic signal. The attention mechanism can tie the price to the product because it recognizes the linguistic pattern it saw millions of times during pre-training.

How I flatten product data

/**
 * Flattens product data into a semantically rich string for embeddings.
 * Prefixing with bbioon_ as per my standard workflow.
 */
function bbioon_flatten_product_for_ai( $product_id ) {
    $product = wc_get_product( $product_id );
    
    if ( ! $product ) return '';

    // Create a natural language string
    return sprintf(
        "Product: %s. Brand: %s. This item costs %s %s and is currently %s.",
        $product->get_name(),
        $product->get_attribute('brand') ?: 'Generic',
        $product->get_price(),
        get_woocommerce_currency(),
        $product->is_in_stock() ? 'available in stock' : 'out of stock'
    );
}

// Result: Product: Vintage Leather Boots. Brand: Timberland. This item costs 150 USD and is currently available in stock.

Switch to prose and MRR (Mean Reciprocal Rank) and Precision@K both move right away. You stop fighting the model and start giving it the kind of text it handles well.

If this vector search optimization work is eating your dev hours, I can take it on. I have been working with WordPress since the 4.x days and I have seen how these AI integrations break under load.

Data prep beats shiny tools

The newest vector database features and HNSW tuning are not where the win is. As long as the underlying data goes in as raw JSON, retrieval stays worse than it needs to be. Flatten the data, use natural language templates, and the RAG results settle down. I also wrote about not over-engineering your vector DB if you want the other half of this.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.