Lab - Extend the Schema and Query
In this lab you will extend the product schema from Lab 1 with more fields, feed a richer dataset, practice partial updates, and write YQL queries with filters, sorting, and pagination. You will also add a custom document summary.
Prerequisites
Your Vespa container from Lab 1 should be running with the ecommerce-app deployed. If you stopped it, restart with docker start vespa.

Extend the Schema
Open ecommerce-app/schemas/product.sd and replace its contents with this expanded schema:
schema product {
document product {
field title type string {
indexing: summary | index
index: enable-bm25
}
field description type string {
indexing: summary | index
index: enable-bm25
}
field category type string {
indexing: summary | attribute
attribute: fast-search
}
field brand type string {
indexing: summary | attribute
attribute: fast-search
}
field price type int {
indexing: summary | attribute
}
field rating type float {
indexing: summary | attribute
}
field in_stock type bool {
indexing: summary | attribute
}
field color type string {
indexing: summary | attribute
}
field updated_at type long {
indexing: summary | attribute
}
}
fieldset default {
fields: title, description
}
document-summary short {
summary title {}
summary price {}
summary brand {}
summary in_stock {}
}
}
What changed from Lab 1:
index: enable-bm25ontitleanddescriptionenables BM25 scoring (we will use this in Lab 4)descriptionis a new indexed text field for full-text searchbrandandcategoryhaveattribute: fast-searchfor efficient filteringrating,in_stock,color, andupdated_atare new attribute fields- A
defaultfieldset lets you searchtitleanddescriptiontogether - A
shortdocument summary returns only a few fields, reducing response size
Redeploy
vespa deploy --wait 300 ecommerce-app
Vespa applies schema changes live. Your existing data is still there, but the old 10 documents do not have the new fields. Let's re-feed with a richer dataset.
Feed the Extended Dataset
Create feed-extended.jsonl. Here is a larger set of products with all fields populated:
{"put": "id:product:product::1", "fields": {"title": "Cotton crew neck t-shirt", "description": "Soft breathable cotton t-shirt with a classic crew neck. Perfect for everyday wear in warm weather.", "category": "Tops", "brand": "BasicWear", "price": 29, "rating": 4.2, "in_stock": true, "color": "White", "updated_at": 1709251200}}
{"put": "id:product:product::2", "fields": {"title": "Slim fit jeans dark blue", "description": "Classic slim fit jeans in dark blue wash. Stretch denim for comfort throughout the day.", "category": "Bottoms", "brand": "DenimCo", "price": 79, "rating": 4.5, "in_stock": true, "color": "Blue", "updated_at": 1709164800}}
{"put": "id:product:product::3", "fields": {"title": "Running shoes lightweight mesh", "description": "Lightweight running shoes with breathable mesh upper and responsive foam sole. Great for daily training.", "category": "Shoes", "brand": "SpeedStep", "price": 120, "rating": 4.7, "in_stock": true, "color": "Black", "updated_at": 1709078400}}
{"put": "id:product:product::4", "fields": {"title": "Waterproof hiking jacket", "description": "Fully waterproof jacket with sealed seams and adjustable hood. Three-layer fabric for mountain conditions.", "category": "Outerwear", "brand": "TrailPeak", "price": 189, "rating": 4.8, "in_stock": false, "color": "Green", "updated_at": 1708992000}}
{"put": "id:product:product::5", "fields": {"title": "Leather crossbody bag", "description": "Genuine leather crossbody bag with adjustable strap. Multiple compartments for phone, wallet, and essentials.", "category": "Accessories", "brand": "UrbanCraft", "price": 65, "rating": 4.1, "in_stock": true, "color": "Brown", "updated_at": 1708905600}}
{"put": "id:product:product::6", "fields": {"title": "Wool blend overcoat", "description": "Elegant wool blend overcoat with notch lapels. Fully lined for warmth in cold weather.", "category": "Outerwear", "brand": "ClassicLine", "price": 250, "rating": 4.6, "in_stock": true, "color": "Grey", "updated_at": 1708819200}}
{"put": "id:product:product::7", "fields": {"title": "Striped cotton polo shirt", "description": "Classic polo shirt with horizontal stripes. Ribbed collar and two-button placket.", "category": "Tops", "brand": "BasicWear", "price": 45, "rating": 4.0, "in_stock": true, "color": "Blue", "updated_at": 1708732800}}
{"put": "id:product:product::8", "fields": {"title": "High-waist yoga leggings", "description": "Four-way stretch yoga leggings with high waistband and hidden pocket. Moisture-wicking fabric.", "category": "Bottoms", "brand": "FlexFit", "price": 55, "rating": 4.4, "in_stock": true, "color": "Black", "updated_at": 1708646400}}
{"put": "id:product:product::9", "fields": {"title": "Canvas sneakers white", "description": "Classic white canvas sneakers with vulcanized rubber sole. Minimal design goes with everything.", "category": "Shoes", "brand": "StreetWalk", "price": 60, "rating": 4.3, "in_stock": true, "color": "White", "updated_at": 1708560000}}
{"put": "id:product:product::10", "fields": {"title": "Stainless steel watch", "description": "Stainless steel watch with sapphire crystal glass and Japanese quartz movement. Water resistant to 50m.", "category": "Accessories", "brand": "TimeCraft", "price": 199, "rating": 4.9, "in_stock": true, "color": "Silver", "updated_at": 1708473600}}
{"put": "id:product:product::11", "fields": {"title": "Fleece zip hoodie", "description": "Warm fleece hoodie with full zip front and kangaroo pockets. Soft brushed interior.", "category": "Tops", "brand": "BasicWear", "price": 59, "rating": 4.3, "in_stock": true, "color": "Grey", "updated_at": 1708387200}}
{"put": "id:product:product::12", "fields": {"title": "Linen shorts casual", "description": "Relaxed fit linen shorts with drawstring waist. Lightweight and breathable for summer.", "category": "Bottoms", "brand": "SummerEase", "price": 42, "rating": 3.9, "in_stock": false, "color": "Beige", "updated_at": 1708300800}}
{"put": "id:product:product::13", "fields": {"title": "Leather ankle boots", "description": "Full grain leather ankle boots with side zip. Durable rubber outsole and cushioned insole.", "category": "Shoes", "brand": "TrailPeak", "price": 165, "rating": 4.6, "in_stock": true, "color": "Brown", "updated_at": 1708214400}}
{"put": "id:product:product::14", "fields": {"title": "Packable rain jacket", "description": "Ultra-light rain jacket that packs into its own pocket. Waterproof with taped seams.", "category": "Outerwear", "brand": "TrailPeak", "price": 85, "rating": 4.2, "in_stock": true, "color": "Navy", "updated_at": 1708128000}}
{"put": "id:product:product::15", "fields": {"title": "Silk scarf printed", "description": "Luxurious silk scarf with hand-rolled edges. Bold geometric print in multiple colors.", "category": "Accessories", "brand": "ClassicLine", "price": 78, "rating": 4.5, "in_stock": true, "color": "Red", "updated_at": 1708041600}}
{"put": "id:product:product::16", "fields": {"title": "Denim jacket classic", "description": "Classic denim jacket in medium wash. Button front with chest pockets and side pockets.", "category": "Outerwear", "brand": "DenimCo", "price": 95, "rating": 4.4, "in_stock": true, "color": "Blue", "updated_at": 1707955200}}
{"put": "id:product:product::17", "fields": {"title": "Performance tank top", "description": "Lightweight tank top with mesh back panel for ventilation. Quick-dry fabric for intense workouts.", "category": "Tops", "brand": "FlexFit", "price": 32, "rating": 4.1, "in_stock": true, "color": "Black", "updated_at": 1707868800}}
{"put": "id:product:product::18", "fields": {"title": "Chino pants slim fit", "description": "Slim fit chino pants in stretch cotton twill. Versatile enough for office or weekend.", "category": "Bottoms", "brand": "ClassicLine", "price": 68, "rating": 4.3, "in_stock": true, "color": "Khaki", "updated_at": 1707782400}}
{"put": "id:product:product::19", "fields": {"title": "Trail running shoes", "description": "Rugged trail running shoes with aggressive tread pattern. Rock plate protects against sharp terrain.", "category": "Shoes", "brand": "SpeedStep", "price": 140, "rating": 4.7, "in_stock": false, "color": "Orange", "updated_at": 1707696000}}
{"put": "id:product:product::20", "fields": {"title": "Polarized sunglasses aviator", "description": "Aviator style sunglasses with polarized lenses and metal frame. UV400 protection.", "category": "Accessories", "brand": "UrbanCraft", "price": 45, "rating": 4.0, "in_stock": true, "color": "Gold", "updated_at": 1707609600}}
Feed it:
vespa feed feed-extended.jsonl
Since we are using the same document IDs for products 1-10, Vespa overwrites the old documents with the new ones that include all fields. Products 11-20 are new.
Practice Partial Updates
Partial updates let you change individual fields without re-feeding the entire document. Let's mark the hiking jacket as back in stock and update the trail running shoes price:
vespa document update id:product:product::4 '{"fields": {"in_stock": {"assign": true}}}'
vespa document update id:product:product::19 '{"fields": {"price": {"assign": 129}}}'
Verify the updates worked:
vespa document get id:product:product::4
The in_stock field should now be true.
Write Queries
Text search across the fieldset
Search both title and description at once using the default fieldset:
vespa query "select * from product where default contains 'leather'"
This matches the crossbody bag (title), the ankle boots (title and description), and potentially others with "leather" in the description.
Filter by attribute
Find all products from the TrailPeak brand:
vespa query "select * from product where brand = 'TrailPeak'"
Combine text search and filters
Search for shoes under $130:
vespa query "select * from product where default contains 'shoes' and price < 130"
Sort results
Get all products sorted by price, cheapest first:
vespa query "select * from product where true order by price asc"
Sort by rating, highest first:
vespa query "select * from product where true order by rating desc"
Pagination
Get the first page of 5 results, then the second page:
vespa query "select * from product where true order by price asc" "hits=5" "offset=0"
vespa query "select * from product where true order by price asc" "hits=5" "offset=5"
Use the short summary
Request just the fields defined in the short document summary:
vespa query "select * from product where true" "summary=short" "hits=5"
The response includes only title, price, brand, and in_stock for each hit, which is less data to transfer.
Find out-of-stock products
vespa query "select * from product where in_stock = false"
Checkpoint
Run this query and verify the result:
vespa query "select * from product where brand = 'BasicWear' and price < 50" "summary=short"
You should see 2 results: the cotton t-shirt (29) and the polo shirt (45). The response should only contain the short summary fields.
What You Built
Your application now has:
- A schema with 9 fields covering text, numeric, boolean, and timestamp data
enable-bm25on text fields for proper relevance scoring (used in Lab 4)fast-searchoncategoryandbrandfor efficient filtering- A
defaultfieldset for searching title and description together - A
shortdocument summary for lightweight responses - 20 products with realistic data
- Experience with partial updates, filtering, sorting, and pagination
In the next lab, you will structure this into a proper application package with query profiles.