Backend Development 14 min read

Integrating Elasticsearch with Spring Boot for Full-Text Product Search

This guide walks through installing Elasticsearch and Kibana, configuring a Chinese analyzer, defining Spring Data Elasticsearch annotations, creating repository and service layers, building a REST controller, and testing product search functionality within a Spring Boot mall application.

macrozheng
macrozheng
macrozheng
Integrating Elasticsearch with Spring Boot for Full-Text Product Search

Project Framework Overview

The article explains how to integrate Elasticsearch into a mall project to enable full‑text search for product information. It covers installation, configuration, data mapping, repository creation, service implementation, and API testing.

Elasticsearch

Elasticsearch is a distributed, scalable, real‑time search and analytics engine. It provides full‑text search and real‑time data statistics from the start of a project.

Installation and Usage

Download the Elasticsearch 6.2.2 zip package from https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-2-2 and unzip it.

Install the Chinese analysis plugin:

<code>elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.2/elasticsearch-analysis-ik-6.2.2.zip</code>

Start Elasticsearch by running

bin\elasticsearch.bat

.

Kibana

Download Kibana 6.2.2 zip from https://artifacts.elastic.co/downloads/kibana/kibana-6.2.2-windows-x86_64.zip and unzip it.

Start Kibana with

bin\kibana.bat

and open http://localhost:5601 in a browser.

Kibana UI
Kibana UI

Spring Data Elasticsearch

Spring Data Elasticsearch provides a Spring‑Data‑style way to operate on Elasticsearch, reducing boilerplate code.

Common Annotations

@Document – maps a class to an Elasticsearch document.

<code>/**
 * Marks the class as an Elasticsearch document.
 */
@Document(indexName = "pms", type = "product", shards = 1, replicas = 0)
public class EsProduct implements Serializable {
    private static final long serialVersionUID = -1L;

    @Id
    private Long id;

    @Field(type = FieldType.Keyword)
    private String productSn;

    @Field(type = FieldType.Keyword)
    private String brandName;

    @Field(type = FieldType.Keyword)
    private String productCategoryName;

    @Field(analyzer = "ik_max_word", type = FieldType.Text)
    private String name;

    @Field(analyzer = "ik_max_word", type = FieldType.Text)
    private String subTitle;

    @Field(analyzer = "ik_max_word", type = FieldType.Text)
    private String keywords;

    // other fields omitted for brevity
}
</code>

@Id – marks the field as the document ID.

@Field – defines field type, analyzer, indexing, and storage options.

<code>@Field(type = FieldType.Keyword) // not tokenized, suitable for exact matches
private String productSn;

@Field(analyzer = "ik_max_word", type = FieldType.Text) // tokenized for full‑text search
private String name;
</code>

Derived Queries

By extending

ElasticsearchRepository

, common CRUD methods are available, and query methods can be defined directly from the method name.

<code>public interface EsProductRepository extends ElasticsearchRepository<EsProduct, Long> {
    Page<EsProduct> findByNameOrSubTitleOrKeywords(String name, String subTitle, String keywords, Pageable page);
}
</code>

Service Layer

The

EsProductService

interface defines operations for importing, creating, and deleting product documents.

<code>public interface EsProductService {
    /** Import all products from the database into Elasticsearch */
    int importAll();

    /** Delete a product by ID */
    void delete(Long id);

    /** Create a product document by ID */
    EsProduct create(Long id);

    /** Batch delete products */
    void delete(List<Long> ids);

    /** Search by keyword with pagination */
    Page<EsProduct> search(String keyword, Integer pageNum, Integer pageSize);
}
</code>

The implementation uses a DAO to fetch product data, then saves it via the repository.

<code>@Service
public class EsProductServiceImpl implements EsProductService {
    private static final Logger LOGGER = LoggerFactory.getLogger(EsProductServiceImpl.class);

    @Autowired
    private EsProductDao productDao;

    @Autowired
    private EsProductRepository productRepository;

    @Override
    public int importAll() {
        List<EsProduct> esProductList = productDao.getAllEsProductList(null);
        Iterable<EsProduct> saved = productRepository.saveAll(esProductList);
        int count = 0;
        for (EsProduct p : saved) {
            count++;
        }
        return count;
    }

    @Override
    public void delete(Long id) {
        productRepository.deleteById(id);
    }

    @Override
    public EsProduct create(Long id) {
        List<EsProduct> list = productDao.getAllEsProductList(id);
        if (!list.isEmpty()) {
            EsProduct esProduct = list.get(0);
            return productRepository.save(esProduct);
        }
        return null;
    }

    @Override
    public void delete(List<Long> ids) {
        List<EsProduct> esProductList = new ArrayList<>();
        for (Long id : ids) {
            EsProduct esProduct = new EsProduct();
            esProduct.setId(id);
            esProductList.add(esProduct);
        }
        productRepository.deleteAll(esProductList);
    }

    @Override
    public Page<EsProduct> search(String keyword, Integer pageNum, Integer pageSize) {
        Pageable pageable = PageRequest.of(pageNum, pageSize);
        return productRepository.findByNameOrSubTitleOrKeywords(keyword, keyword, keyword, pageable);
    }
}
</code>

Controller Layer

The REST controller exposes endpoints for importing data, deleting, creating, and searching products.

<code>@Controller
@Api(tags = "EsProductController", description = "Product search management")
@RequestMapping("/esProduct")
public class EsProductController {
    @Autowired
    private EsProductService esProductService;

    @ApiOperation("Import all products from DB to ES")
    @RequestMapping(value = "/importAll", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<Integer> importAllList() {
        int count = esProductService.importAll();
        return CommonResult.success(count);
    }

    @ApiOperation("Delete product by ID")
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<Object> delete(@PathVariable Long id) {
        esProductService.delete(id);
        return CommonResult.success(null);
    }

    @ApiOperation("Batch delete products by IDs")
    @RequestMapping(value = "/delete/batch", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<Object> delete(@RequestParam("ids") List<Long> ids) {
        esProductService.delete(ids);
        return CommonResult.success(null);
    }

    @ApiOperation("Create product document by ID")
    @RequestMapping(value = "/create/{id}", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<EsProduct> create(@PathVariable Long id) {
        EsProduct esProduct = esProductService.create(id);
        if (esProduct != null) {
            return CommonResult.success(esProduct);
        }
        return CommonResult.failed();
    }

    @ApiOperation("Simple keyword search")
    @RequestMapping(value = "/search/simple", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<CommonPage<EsProduct>> search(
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false, defaultValue = "0") Integer pageNum,
            @RequestParam(required = false, defaultValue = "5") Integer pageSize) {
        Page<EsProduct> esProductPage = esProductService.search(keyword, pageNum, pageSize);
        return CommonResult.success(CommonPage.restPage(esProductPage));
    }
}
</code>

Interface Testing

Import Data from Database to Elasticsearch

Import result
Import result
Import success
Import success

Product Search

Search UI
Search UI
Search results
Search results

Project Source Code

https://github.com/macrozheng/mall-learning/tree/master/mall-tiny-06

Recommended Reading

mall architecture and feature overview

Required knowledge for mall learning (recommended resources)

Integrating SpringBoot+MyBatis to build a basic skeleton

Integrating Swagger‑UI for online API documentation

Integrating Redis for caching

SpringSecurity + JWT authentication (part 1)

SpringSecurity + JWT authentication (part 2)

Integrating SpringTask for scheduled jobs

QR code
QR code

Follow us and give a like!

javaElasticsearchSpring BootSpring DataFull-Text Search
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.