Technical Specification Snapshot
| Parameter | Description |
|---|---|
| Core Technology | Elasticsearch 7.x |
| Language | JSON DSL, Bash |
| Communication Protocol | HTTP/REST |
| Typical Response Target | 10ms-50ms |
| Chinese Tokenization | IK Analyzer |
| Core Dependencies | Lucene, elasticsearch-analysis-ik |
| Typical Scenarios | Article search, product search, log retrieval |
| Star Count | Not provided in the original article |
High-performance full-text search depends on end-to-end design
Efficient full-text search does not come from a single optimization point. It is the result of coordination across tokenization, index structure, query patterns, and hardware resources. If you only know how to write a match query, you will usually run into problems such as poor Chinese tokenization, inaccurate results, unstable deep pagination, and rising latency under high concurrency.
In enterprise scenarios, the goals usually fall into three categories: fast response, accurate relevance, and stable system behavior. In Elasticsearch, these map to inverted index quality, the expressiveness of BM25 scoring, and shard plus cache strategy.
Criteria for evaluating efficient full-text search
- Fast: Common queries maintain millisecond-level response times
- Accurate: Title hits rank higher, and phrase matches are more trustworthy
- Stable: Latency remains controllable under high concurrency, and nodes are not overwhelmed by deep pagination
# Install the IK Chinese analyzer plugin
# Core idea: build a more usable inverted index for Chinese content
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.0/elasticsearch-analysis-ik-7.17.0.zip
This command installs the IK analyzer for Elasticsearch, which is the foundational step for improving Chinese full-text search quality.
Search quality for Chinese begins with the analyzer
Elasticsearch full-text search is built on the principle of analyze first, then index. In Chinese-language scenarios, the default analyzer often fails to capture semantic boundaries and can split text into isolated characters, which directly reduces recall and ranking quality.
IK Analyzer typically provides two modes: ik_max_word works well for indexing and emphasizes recall; ik_smart works well for search-time analysis and emphasizes precision and efficiency. Using them together is a common production setup.
Mapping design defines the upper bound of your queries
Field structure is not just a storage detail. It defines the limits of your query capabilities. A title field usually needs both full-text search and exact filtering or sorting, so a text + keyword multi-field structure is a good fit. Body content, by contrast, usually focuses more on full-text matching and highlighting.
PUT /article_index
{
"settings": {
"number_of_shards": 3,
"refresh_interval": "30s",
"index.sort.field": "create_time"
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"content": {
"type": "text",
"analyzer": "ik_max_word",
"norms": false,
"index_options": "offsets"
},
"create_time": {
"type": "date"
}
}
}
}
This mapping balances Chinese search, exact matching, highlighting, and write performance, making it a practical template for article search.
Query DSL selection directly affects precision and throughput
For single-field search, start with match. It automatically analyzes the query text and participates in relevance scoring, which makes it suitable for fields such as body content and summaries.
GET /article_index/_search
{
"query": {
"match": {
"content": "Elasticsearch 全文检索"
}
}
}
This query performs single-field full-text search and is useful for quickly validating indexing and analyzer behavior.
For multi-field search, multi_match is more common. In article search, the title usually carries more weight than the body, so you can explicitly boost the title with title^3.
GET /article_index/_search
{
"query": {
"multi_match": {
"query": "Elasticsearch 全文检索",
"fields": ["title^3", "content"],
"type": "best_fields"
}
}
}
This query searches both the title and body while improving ranking accuracy through field boosting.
Phrase queries and filter queries should be clearly separated
When the business requirement demands exact word order, such as searching for “high-performance full-text search,” use match_phrase. This avoids false positives caused by scattered token matches after analysis.
GET /article_index/_search
{
"query": {
"match_phrase": {
"content": "高效全文检索"
}
}
}
This query enforces phrase order consistency and fits high-precision scenarios such as titles, slogans, and technical terms.
If you need both search and structured filtering by time, status, or tenant, use bool + filter. Because filter does not affect scoring, it is also more likely to benefit from caching.
GET /article_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"content": "全文检索"
}
}
],
"filter": [
{
"range": {
"create_time": {
"gte": "2024-01-01"
}
}
}
]
}
}
}
This query separates search from filtering, which preserves precision while reducing computation cost.
Search UX improves when highlighting and pagination strategy work together
Without highlighting, users cannot quickly understand why a result matched. When enabling highlighting for body content, configure index_options: offsets in the mapping stage to reduce highlight overhead.
GET /article_index/_search
{
"query": {
"match": {
"content": "全文检索"
}
},
"highlight": {
"fields": {
"content": {}
},
"pre_tags": ["<em>"],
"post_tags": ["</em>"]
}
}
This query generates highlighted snippets for matched terms and can be used directly in a search results page.
Deep pagination is one of the most common Elasticsearch performance traps. Once from + size reaches large offsets, sorting and merge costs increase significantly. In production, prefer search_after instead.
Key optimization strategies that make search faster
- Return only the fields you actually need to reduce
_sourcepayload size - Put filter conditions in
filterwhenever possible to avoid unnecessary scoring - Keep each shard around 30GB-50GB to avoid too many tiny shards
- Enable
routingby user or tenant for hotspot workloads - Turn on request cache to stabilize repeated query latency
- Use SSDs to reduce inverted index reads and segment merge cost
- Use coordinating nodes to distribute requests and reduce pressure on data nodes
GET /article_index/_search
{
"_source": ["title", "content"],
"request_cache": true,
"query": {
"match": {
"content": "全文检索"
}
}
}
This query demonstrates field filtering and request caching, both of which can directly reduce query latency and network overhead.
An enterprise-ready solution should cover relevance, capacity, and stability together
A reusable enterprise-grade solution usually includes the IK analyzer, a text + keyword field model, weighted multi_match queries, bool filter constraints, search_after for deep pagination, request caching, sensible shard sizing, and SSD storage.
If the dataset grows to hundreds of millions of documents, add replicas to protect read throughput, use coordinating nodes to absorb entry traffic, and apply cache warming plus routing convergence for hot indexes. That is how you move from a search system that merely works to one that delivers sustainable high performance.
AI Visual Insight: This image appears at the end of the original article and serves mainly as a visual aid. Based on the context, it should be treated as an illustrative search-system graphic or a closing visual element rather than a source of concrete architectural parameters. It should not be used as a basis for technical decisions, but it does help confirm that the original article uses imagery to improve reading rhythm.
FAQ
1. Why should Chinese search prioritize the analyzer first?
Because the inverted index is built from the tokenization result. If Chinese text is split incorrectly, even the best Query DSL cannot recover the lost recall and ranking quality. In production, teams usually adopt IK first and separate indexing analysis from search-time analysis.
2. Why should filter conditions go into filter instead of must?
filter does not participate in relevance scoring, so it uses less CPU and is more cache-friendly. Structured constraints such as time ranges, status values, and tenant IDs do not need scoring in the first place, so placing them in filter is the better choice.
3. Why is deep pagination slow in Elasticsearch, and how should you handle it?
Because deep pagination forces each shard to collect a large candidate set first, and then the coordinating phase must perform global sorting and merging. That increases both memory and CPU cost. In production, prefer search_after or scroll queries instead of large-offset pagination.
Core summary
This article systematically reconstructs a practical Elasticsearch full-text search solution, covering the IK analyzer, mapping design, match and multi_match queries, highlighting, pagination, caching, shards, and SSD optimization. It helps developers build millisecond-level, scalable, enterprise-grade search services.