How Elasticsearch Product Search Works in the mall‑search Module
The mall‑search module implements a full‑text product search layer using Spring Data Elasticsearch, synchronizing data from MySQL to Elasticsearch and exposing REST endpoints for keyword search, filtered queries, recommendations, and aggregations.
The mall-search module in the macrozheng/mall repository provides the search infrastructure for the e‑commerce platform. It bridges the relational MySQL database with Elasticsearch to deliver fast, relevance‑scored product discovery. Understanding this implementation reveals how to build scalable search features using Spring Data Elasticsearch and the Elasticsearch Java client.
Architecture Overview
The module follows a three‑layer pattern separating data synchronization, query construction, and HTTP exposure. The data‑sync layer pulls records from MySQL via MyBatis, the search service layer builds native Elasticsearch queries using NativeSearchQueryBuilder, and the API layer exposes REST endpoints through EsProductController.
Key components include:
EsProductServiceImpl.java– Core search logic and query constructionEsProductRepository.java– Spring Data Elasticsearch repository interfaceEsProductController.java– REST endpoints at/esProductEsProductDao.java– MyBatis DAO for database reads
Data Synchronization from MySQL to Elasticsearch
Before any search executes, product data must be indexed. The importAll() method in EsProductServiceImpl orchestrates a full import:
// EsProductServiceImpl.java lines 61-71
int importAll() {
List<EsProduct> esProductList = esProductDao.getAllEsProductList(null);
Iterable<EsProduct> esProductIterable = productRepository.saveAll(esProductList);
// ... count and return
}
EsProductDao executes a MyBatis query defined in mall-search/src/main/resources/dao/EsProductDao.xml to select from the pms_product table. The resulting list is bulk‑stored via productRepository.saveAll, a Spring Data Elasticsearch method that performs a _bulk index operation.
Search Implementation Strategies
The module offers two search modes: a simple derived query for basic keyword matching and a programmatic NativeSearchQuery for complex filtering and relevance tuning.
Simple Keyword Search
For unfiltered keyword searches, the service delegates to a derived query method in EsProductRepository:
// EsProductRepository.java
Page<EsProduct> findByNameOrSubTitleOrKeywords(
String name, String subTitle, String keywords, Pageable page);
Spring Data Elasticsearch automatically generates a bool should query that matches the keyword against the name, subTitle, or keywords fields. This approach requires no manual query construction but offers limited relevance tuning.
Advanced Search with Filtering and Sorting
The search(...) method in EsProductServiceImpl (lines 110–170) builds a sophisticated NativeSearchQuery combining full‑text scoring, term filters, and configurable sorting.
Query Construction Logic:
- Term Filters – Optional
brandIdandproductCategoryIdparameters are added to aBoolQueryBuilderastermclauses to narrow results. - Function Scoring – When a keyword is provided, three
matchqueries targetname(weight 10),subTitle(weight 5), andkeywords(weight 2). These are wrapped in afunction_scorequery usingScoreFunctionBuilders.weightFactorFunctionwith a minimum score threshold of 2. - Sorting Strategy – The integer
sortparameter selects the finalSortBuilder:1→iddesc (newest)2→saledesc (best‑selling)3→priceasc (price low‑to‑high)4→pricedesc (price high‑to‑low)- Default →
_scoredesc (relevance)
The query executes via ElasticsearchRestTemplate.search, and hits are mapped to EsProduct entities before being wrapped in a Spring Page object.
Product Recommendations
The recommend(Long id, Integer pageNum, Integer pageSize) method generates "similar products" by analyzing a reference item. Located in EsProductServiceImpl, it:
- Retrieves the source product by ID
- Builds a
functionScorequery matching the product'sname,subTitle, andkeywords - Adds boosted term matches:
brandId(weight 5) andproductCategoryId(weight 3) - Excludes the original product using a
mustNotfilter on theidfield
This approach surfaces items sharing brand or category while maintaining textual relevance, executed through the same ElasticsearchRestTemplate pattern as the advanced search.
Aggregations for Filter Data
To populate UI filter panels, searchRelatedInfo(String keyword) (lines 190+) executes three aggregations:
- Brand aggregation –
termsonbrandNameto collect available brands - Category aggregation –
termsonproductCategoryNamefor category facets - Attribute aggregation – A nested aggregation on
attrValueList(type = 1) collecting attribute IDs, values, and names
The raw Aggregations object is transformed in convertProductRelatedInfo(...) into an EsProductRelatedInfo DTO, providing structured data for faceted navigation without returning full product documents.
REST API Endpoints
Clients interact with the search capabilities through EsProductController endpoints:
GET /esProduct/search/simple?keyword=phone&pageNum=0&pageSize=10
Triggers the simple derived query through findByNameOrSubTitleOrKeywords.
GET /esProduct/search?keyword=phone&brandId=3&sort=3&pageNum=0&pageSize=10
Executes the advanced function‑score search with brand filtering and price‑ascending sort.
GET /esProduct/recommend/42?pageNum=0&pageSize=5
Returns similar products while excluding the original item (ID 42).
GET /esProduct/search/relate?keyword=phone
Returns aggregation results containing distinct brandNames, productCategoryNames, and product attributes for the keyword "phone".
Summary
- Data flow –
EsProductDaoqueries MySQL,importAll()bulk‑indexes into Elasticsearch viaEsProductRepository.saveAll - Simple search – Uses Spring Data’s derived query
findByNameOrSubTitleOrKeywordsfor basic keyword matching - Advanced search – Programmatic
NativeSearchQuerywithBoolQueryBuilderfor filters,functionScorefor weighted field relevance (10/5/2), and dynamic sorting - Recommendations – Function‑score query boosting
brandId(5) andproductCategoryId(3) while excluding the source product - Aggregations – Multi‑bucket terms aggregations on brands, categories, and nested attributes to drive filter UIs
Frequently Asked Questions
How does the mall‑search module synchronize product data with Elasticsearch?
The synchronization occurs through the importAll() method in EsProductServiceImpl.java. This method calls EsProductDao.getAllEsProductList(null) to fetch all product records from MySQL using MyBatis, then invokes productRepository.saveAll() to perform a bulk index operation into Elasticsearch. This establishes the initial searchable document corpus.
What relevance scoring algorithm does the advanced product search use?
The advanced search implements a function score query defined in EsProductServiceImpl.java. It assigns weight factors to three matched fields: name receives a weight of 10, subTitle receives 5, and keywords receives 2. These individual match scores are summed, and a minimum score of 2 is enforced to filter out low‑relevance results, ensuring brand and title matches rank higher than keyword matches.
How are product recommendations generated in the recommendation endpoint?
The recommend(Long id, ...) method retrieves the reference product, extracts its textual fields and categorical data, then constructs a function score query that boosts matches on the same brandId (weight 5) and productCategoryId (weight 3). A mustNot clause excludes the original product by ID, returning a ranked list of similar items based on shared brand affinity, category, and textual content.
What sorting options are available in the product search API?
The sort parameter in the advanced search endpoint accepts integer values controlling the SortBuilder: 1 sorts by ID descending (newest), 2 by sales volume descending (best‑selling), 3 by price ascending (low‑to‑high), 4 by price descending (high‑to‑low), and any other value defaults to _score descending (relevance). This allows users to switch between discovery modes programmatically.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →