AI moodboards for fashion: from relational database to vector search
by Sergej Subkov
A product catalog can be fully documented and still fail to answer the most important question: does this piece fit the mood we want?
A mid-sized manufacturer designs and produces fashion accessories for the fashion and sportswear industry: buckles, buttons, D-rings, fasteners, zippers and numerous decorative elements.
Twice a year, new collections appear with around 1,500 articles. At the start of each season, themes and moodboards are created. Designers set a creative direction, for example:
Warm, brushed metals, Art Deco geometry and muted earth tones.
They then look for products that fit this mood.
The problem was never a lack of choice. The problem was finding exactly the right products in a very large catalog.
"Does this fit the mood?" is not a keyword search
A classic product search works with structured attributes:
- article number
- category
- material
- color code
- dimensions
These details matter, but they do not answer the central question when building a theme or moodboard:
Does this product feel right for the new collection?
This is about visual and creative qualities:
- surface
- shape
- material impression
- style
- character
- historical or cultural associations
These attributes are not reliably captured in individual database columns.
Staff went through the catalog image by image and picked out products that matched the intended mood. This was time-consuming, depended heavily on personal product knowledge and did not scale with a range that grows by roughly 3,000 new articles every year.
Our goal was therefore:
Designers should be able to describe a mood in natural language and find matching products straight away.
The approach: translating product images into meaning
Semantic search does not work through identical terms, but through similarity of content. To achieve this, each item of content is represented as what is called an embedding: a numerical vector that captures its semantic properties.
In this vector space, similar content sits closer together than dissimilar content. The search is then no longer a classic text comparison, but a distance computation:
- Product images are translated into vectors.
- The search query is likewise translated into a vector.
- The system looks for the product vectors with the smallest distance to the query.
Our processing pipeline runs offline in three steps.
1. Describe the product image
Every product photo is analyzed by a vision model.
The model produces a detailed description of what a designer would perceive in the image, for example:
- shape
- surface texture
- finish
- color effect
- style
- decorative features
The description should not merely state that it is, say, a buckle. It should capture how the product works as a design.
2. Embed the description
From the generated description, a high-dimensional embedding is created. In the production application, each vector has 3,072 dimensions.
3. Store and index the vector
The embedding is stored together with the product and indexed for later search.
When a designer then enters a mood, that query is embedded as well. The system then returns the products whose vectors lie closest to the query.
Describing and embedding the products was not the technically hardest part.
The real architectural question was:
How do we store and search millions of high-dimensional numbers reliably and quickly?
Version 1: Similarity Search with MySQL
The company already ran a MySQL database. The pragmatic first step was therefore to store the embeddings there. Each embedding sat as a JSON column next to the corresponding product record.
The Similarity Search took place in the application code:
- load relevant records from MySQL
- compare each embedding against the query vector
- compute cosine similarity
- sort the results
- filter against a threshold
- return the best matches
For getting started, this was the right decision.
The first version:
- could be implemented quickly
- required no additional infrastructure
- used the existing backups and operational processes
- kept products and embeddings together in the existing data model
- made it possible to check early whether semantic search actually delivered value
For a limited part of the catalog, the response times were sufficient at first.
The limit of the approach: load first, then compute
MySQL stores the embeddings, but cannot compute a semantic distance between vectors. The similarity therefore had to be produced outside the database: for each query, the application first loaded all relevant embeddings from MySQL into memory and only there computed — vector by vector — the distance to the query.
The database could not narrow anything down in advance. Every search was thus a full brute-force scan: first load the entire inventory, then compare everything. A growing catalog only made this worse. But the cause was not the size, it was the order — load first, then compute.
To keep response times tolerable, we optimized the application code:
- Records were loaded page by page.
- Computations ran in parallel across multiple CPU cores.
- The best matches were kept continuously in a bounded data structure.
- Unnecessary results were discarded as early as possible.
These measures improved execution, but did not solve the actual problem. A classic relational database understands no semantic distance between vectors. It cannot:
- use a suitable vector index
- narrow the search space in a targeted way
- determine near neighbors without a full comparison
- avoid reading large parts of the index
The application thus took on, in memory, tasks for which the database itself had no suitable structures.
Storing vectors in a relational database was easy.
Searching them efficiently was not.
Version 2: a specialized vector database
For the second version, we moved the search path onto Qdrant, a database built specifically for vector search.
Approximate Nearest Neighbor Search
Qdrant uses an HNSW index for approximate Nearest Neighbor Search.
Instead of checking every stored vector in full against the query, the database navigates through a graph structure. This lets it reach very similar vectors without having to look at the bulk of the inventory one by one.
The application no longer has to load and compare the entire vector inventory for this.
Vector distance as a native operation
Cosine similarity in the vector database is not a loop bolted on afterwards in the application code, but a core database operation. The search engine can optimize its internal data structures specifically for it.
Metadata filters within the same search operation
Each vector additionally carries a payload with metadata, for example:
- product ID
- image reference
- collection
- import batch
- category
- URL
This allows the semantic search to be narrowed already during the vector query. A designer can, for instance, search only within the current collection or a specific product group, without first generating a large, irrelevant result space.
MySQL remains the source of truth
Despite the switch, we did not replace MySQL.
The relational database remains the leading system. Every embedding continues to be stored there permanently together with the product record.
Qdrant, by contrast, we treat as a specialized search index.
The architecture thus follows a clear division of responsibilities:
MySQL
- leading product inventory
- permanent storage
- existing backups
- transactions
- established operational processes
Qdrant
- vector index
- fast similarity search
- HNSW navigation
- semantic retrieval
- combined metadata filters
The vector data is synchronized from MySQL to Qdrant.
Should the vector service fail or the index become corrupted, no leading product data is lost. The search index can be rebuilt from the relational database. In that case the application can degrade in a controlled way, rather than losing its primary data.
Why the first version was the right choice all the same
The implementation in MySQL was not an unnecessary detour.
It allowed us to answer the decisive questions early and with little infrastructure effort:
- Is a meaning-based search genuinely helpful for the designers?
- Do the image descriptions produce relevant results?
- Do the embeddings understand creative terms well enough?
- Do staff use the feature in their day-to-day work?
- Which filters and views are actually needed?
A vector database would not have answered these product questions. It would merely have introduced additional infrastructure earlier.
The first version was therefore a deliberate decision:
First build the simplest system and use it to validate both feasibility and value.
The concrete benefit for the designers
Previously, building a moodboard began with a laborious manual search.
Staff had to remember which products from a very large historical catalog might fit the current design direction. They then searched through image inventories and product lists for suitable candidates.
Today, a designer can describe the desired mood directly.
For example:
Dark, matte metal with an industrial character, clean geometric shapes and a high-quality, understated feel.
The system translates this description into a vector and looks for products with similar visual and stylistic meaning.
Within seconds, a selection of accessories emerges that can serve as a starting point for the moodboard.
The application does not replace the creative decision. It shortens the path to a relevant shortlist.
What we take away from this
Semantic search consists of more than an embedding model. The actual product solution needs a complete processing pipeline:
- analyze images
- describe visual properties in words
- embed the descriptions
- store the vectors permanently
- synchronize the search index
- filter metadata
- rank and present results
- handle failures in a controlled way
For a prototype, a relational database can be a sensible starting point. It reduces complexity and enables quick validation of the business value. In the long run, however, it is rarely the right place for a large similarity search.
The viable architecture therefore lay not in replacing the relational database, but in using both systems in a targeted way:
MySQL remains the source of truth. Qdrant handles the semantic search.
In this way, the application combines scalable retrieval with the existing data model, the familiar operational processes and the necessary recoverability.
For teams evaluating a semantic search, this leads to a pragmatic order of steps:
- First validate the business pipeline with as little additional infrastructure as possible.
- Measure relevance and actual usage.
- Observe the limits of the first approach.
- Introduce a specialized vector index as the data grows.
- Continue to use the relational database as the leading system.
- Design the search index so that it can be rebuilt at any time.
The most important architectural principle here is:
First prove the value, then specialize the search.