Easy-Es 2.1.0-easysearch: A New Milestone in Domestic Search Engine Integration

Release Overview

This release marks a significant collaboration between INFINI Labs and the Dromara open source community. The Easy-Es framwork now supports Easysearch, a domestically-developed search engine, representing a major step forward in the localization of search technology infrastructure.

Key resources:

Why Integrate with Easysearch?

As organizations increasingly prioritize domestically-controlled technology solutions, the demand for compliant infrastructure has grown substantially. Easysearch provides compelling advantages:

  • Full Domestic Ownership: Completely self-developed with no licensing concerns, meeting national procurement requirements
  • Minimal Resource Footprint: Lower memory and CPU usage compared to traditional engines, with faster startup times
  • Impressive Performance: Optimized query execution suitable for most production workloads
  • Elasticsearch Compatibility: Near-complete API compatibility enables straightforward migrations with minimal friction

Framework Features

Easy-Es delivers substantial improvements in developer productivity:

  1. Reduced Boilerplate: Typical operations require 50-80% less code than native client calls.
// Query execution with minimal configuration
List<Document> docs = documentMapper.selectList(
    EsWrappers.lambdaQuery(Document.class).eq(Document::getTitle, "example")
);

  1. Automated Index Management: The framework handles index lifecycle operations including creation, updates, and data migration with zero downtime.
  2. SQL Compatibility: Familiar SQL patterns work for search queries—supporting and, or, like, in operators.
  3. Type-Safe Field Access: Lambda expressions prevent field name typos and enhance IDE support.
  4. Spring Boot Integration: Auto-configuration and actuator endpoints integrate seamlessly with standard Spring Boot applications.
  5. Advanced Query Support: Nested queries, aggregations, range filters, and highlighting are all supported through a cleen API.
  6. Cluster-Ready: Built-in support for distributed deployments with high availability and horizontal scaling.
  7. Production-Validated: Extensive real-world usage across Chinese enterprises with active community support.

Getting Started

Dependency Configuration

Maven Projects

<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <spring-boot.version>2.7.0</spring-boot.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.dromara.easy-es</groupId>
        <artifactId>easy-es-boot-starter</artifactId>
        <version>2.1.0-easysearch</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>${spring-boot.version}</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Gradle Projects

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.0'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
}

group = 'com.example'
version = '1.0.0'
sourceCompatibility = '11'

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    implementation 'org.dromara.easy-es:easy-es-boot-starter:2.1.0-easysearch'
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

Application Configuration

Update your application.yml to match you're Easysearch deployment:

easy-es:
  enable: true
  address: localhost:9200
  schema: https
  username: admin
  password: your_secure_password
  keep-alive-millis: 18000

  global-config:
    i-kun-mode: true
    process-index-mode: smoothly
    async-process-index-blocking: true
    print-dsl: false
    db-config:
      map-underscore-to-camel-case: true
      index-prefix: prod_
      id-type: customize
      field-strategy: not_empty
      refresh-policy: immediate
      enable-track-total-hits: true

Entity Definition

package com.example.search.entity;

import lombok.Data;
import lombok.experimental.Accessors;
import org.dromara.easyes.annotation.HighLight;
import org.dromara.easyes.annotation.IndexField;
import org.dromara.easyes.annotation.IndexId;
import org.dromara.easyes.annotation.IndexName;
import org.dromara.easyes.annotation.Settings;
import org.dromara.easyes.annotation.rely.Analyzer;
import org.dromara.easyes.annotation.rely.FieldStrategy;
import org.dromara.easyes.annotation.rely.FieldType;
import org.dromara.easyes.annotation.rely.IdType;

import java.time.LocalDateTime;

/**
 * Search document model
 */
@Data
@Accessors(chain = true)
@Settings(shardsNum = 3, replicasNum = 2)
@IndexName(value = "articles", keepGlobalPrefix = true)
public class Article {
    @IndexId(type = IdType.CUSTOMIZE)
    private String id;

    private String title;

    @HighLight(mappingField = "highlightedContent")
    @IndexField(fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART)
    private String content;

    @IndexField(strategy = FieldStrategy.NOT_EMPTY)
    private String author;

    @IndexField(fieldType = FieldType.DATE, dateFormat = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime publishDate;

    private String highlightedContent;

    private Integer viewCount;

    @IndexField(fieldType = FieldType.GEO_POINT)
    private String geoLocation;
}

Mapper Interface

package com.example.search.mapper;

import org.dromara.easyes.core.kernel.BaseEsMapper;
import com.example.search.entity.Article;

public interface ArticleMapper extends BaseEsMapper<Article> {
}

Application Entry Point

package com.example.search;

import org.dromara.easyes.spring.annotation.EsMapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EsMapperScan("com.example.search.mapper")
public class SearchApplication {
    public static void main(String[] args) {
        SpringApplication.run(SearchApplication.class, args);
    }
}

Service Implementation

package com.example.search.controller;

import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import com.example.search.entity.Article;
import com.example.search.mapper.ArticleMapper;
import org.easysearch.action.search.SearchResponse;
import org.easysearch.search.aggregations.Aggregations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

@RestController
public class ArticleController {

    @Resource
    private ArticleMapper articleMapper;

    @GetMapping("/create")
    public int createSampleData() {
        int total = 0;
        for (int i = 1; i <= 5; i++) {
            Article article = new Article();
            article.setId(String.valueOf(i));
            article.setTitle("Sample Article " + i);
            article.setContent("Content body " + i);
            article.setAuthor("Author " + i);
            article.setPublishDate(LocalDateTime.now());
            article.setViewCount(i * 100);
            total += articleMapper.insert(article);
        }
        return total;
    }

    @GetMapping("/findByTitle")
    public List<Article> findByTitle(@RequestParam String title) {
        LambdaEsQueryWrapper<Article> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.eq(Article::getTitle, title);
        return articleMapper.selectList(wrapper);
    }

    @GetMapping("/search")
    public List<Article> search(@RequestParam String keyword) {
        LambdaEsQueryWrapper<Article> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.match(Article::getContent, keyword);
        return articleMapper.selectList(wrapper);
    }

    @GetMapping("/all")
    public List<Article> findAll() {
        LambdaEsQueryWrapper<Article> wrapper = new LambdaEsQueryWrapper<>();
        return articleMapper.selectList(wrapper);
    }

    @GetMapping("/stats")
    public Aggregations getStatistics() {
        LambdaEsQueryWrapper<Article> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.groupBy(Article::getPublishDate)
                .max(Article::getViewCount)
                .min(Article::getViewCount);
        SearchResponse response = articleMapper.search(wrapper);
        return response.getAggregations();
    }

    @GetMapping("/sqlQuery")
    public String executeSqlQuery(@RequestParam(required = false) String title) {
        String sql;
        if (title != null && !title.isEmpty()) {
            sql = String.format("SELECT * FROM prod_articles WHERE title = '%s'", title);
        } else {
            sql = "SELECT * FROM prod_articles LIMIT 10";
        }
        return articleMapper.executeSQL(sql);
    }
}

Testing the Integration

Once the application is running, verify functionality with these endpoints:

# Initialize sample documents
curl http://localhost:8080/create

# Retrieve all documents
curl http://localhost:8080/all

# Find by exact title match
curl "http://localhost:8080/findByTitle?title=Sample Article 1"

# Full-text search
curl "http://localhost:8080/search?keyword=Content"

# SQL-style query
curl "http://localhost:8080/sqlQuery?title=Sample Article 2"

# Aggregation statistics
curl http://localhost:8080/stats

Additional Resources

Tags: Easysearch Easy-Es Elasticsearch ORM Spring Boot integration Search Engine

Posted on Mon, 03 Aug 2026 16:53:31 +0000 by crabfinger