Hologres versions 4.0 and later support a full-text inverted index. This feature is built on the high-performance full-text search engine Tantivy. It also supports the BM25 similarity scoring algorithm, enabling document ranking, keyword search, and phrase search.
How it works
When you write source text to Hologres, it builds a full-text inverted index file for each data file based on the index configuration. The process begins when a tokenizer breaks the text into tokens. The index then records the mapping of each token to its source text, along with its position and term frequency.
When you perform a full-text search, Hologres first tokenizes the query text into a set of query tokens. Hologres then uses the BM25 algorithm to calculate a relevance score for each source text against the set of query tokens. This process enables high-performance and high-precision full-text search.
Considerations
In Hologres V4.0 and later, full-text inverted indexes are supported only on column-store and hybrid row-column store tables, not on row-store tables.
You can create a full-text inverted index only on TEXT, CHAR, or VARCHAR columns.
You can build only one full-text inverted index per column. To index multiple columns, create a separate index for each.
After you create a full-text inverted index, the index files for existing and newly bulk-loaded data are built asynchronously during data compaction. Until the index is built, the BM25 relevance score for the data is 0.
The indexing behavior for real-time data writes varies by version. Before V4.0.8, indexes are built synchronously. Starting from V4.0.8, to improve write efficiency, the system refreshes the in-memory index asynchronously every second. You can query data using the index only after a refresh completes.
You can perform a full-text search only on columns that have a full-text inverted index. Searching columns without an index is not supported.
We recommend using Serverless resources for bulk data imports. These resources perform compaction and build the full-text inverted index synchronously during the import process. For more information, see Use Serverless Computing to perform read and write tasks and Use Serverless Computing to perform Compaction tasks. If you do not use Serverless resources, we recommend that you manually trigger compaction after a bulk import or an index modification with the following command.
VACUUM <schema_name>.<table_name>;The BM25 search algorithm calculates relevance scores at the file level. If you import data in small batches, we recommend manually triggering compaction as needed to merge data files and improve search accuracy.
You can use Serverless resources to execute full-text search queries.
Use the following table to choose the appropriate tokenizer for your scenario:
Scenario
Tokenizer
Description
Keyword extraction from long articles
Jieba
Supports new-word discovery and complex mode switching.
Searching Chinese descriptive text
IK
Accurately identifies Chinese terms.
Searching English title-like text
Simple, Whitespace, Standard
Simple and efficient. Choose one based on your specific text.
Fuzzy search on log-like text
Ngram
Dictionary-free and suitable for fuzzy text queries.
Pinyin-based search for Chinese product or person names
Pinyin
Supports various Chinese Pinyin search scenarios, including full Pinyin, first-letter abbreviations, and characters with multiple pronunciations.
Manage indexes
Create an index
Syntax
CREATE INDEX [ IF NOT EXISTS ] idx_name ON table_name
USING FULLTEXT (column_name [ , ... ])
[ WITH ( storage_parameter [ = value ] [ , ... ] ) ];Parameters
Parameter | Description |
idx_name | The index name. |
table_name | The name of the target table. |
column_name | The column for the full-text inverted index. |
storage_parameter | Specifies the parameters for the full-text inverted index. The following parameters are supported:
Note Each index supports only one |
index_options configuration
The index_options parameter supports three levels. Higher-level options automatically include all information from lower levels: freqs includes all information from docs, and positions includes all information from freqs and docs.
Value | Index content | Impact and limitations | Use cases |
positions (default) | document ID + term frequency + position | Full feature support: Supports phrase queries and standard relevance scoring. | General full-text search scenarios. |
freqs | document ID + term frequency | Phrase queries are not supported and return an error. | Scenarios that require scoring and ranking based on term frequency but do not need exact phrase matching. |
docs | Only document ID |
| Ideal for storage-sensitive scenarios that require only existence checks (filtering) and do not need relevance scoring. |
For indexes that use the keyword tokenizer, the record level is fixed to docs, and the index_options setting does not apply.
Examples
Create a full-text inverted index with the default tokenizer and configuration (the
jiebatokenizer).CREATE INDEX idx1 ON tbl USING FULLTEXT (col1);Explicitly specify the
iktokenizer and use its default configuration.CREATE INDEX idx1 ON tbl USING FULLTEXT (col1) WITH (tokenizer = 'ik');Explicitly specify a custom tokenizer configuration: the
jiebatokenizer inexactmode with only thelowercasefilter.CREATE INDEX idx1 ON tbl USING FULLTEXT (col1) WITH (tokenizer = 'jieba', analyzer_params = '{"tokenizer":{"type":"jieba","mode":"exact"}, "filter":["lowercase"]}');Set
index_optionstofreqswhen creating the index. This saves space but does not support phrase queries. Supported since Hologres V4.1.9.CREATE INDEX idx1 ON tbl USING FULLTEXT (col1) WITH (index_options = 'freqs');
After you create a full-text inverted index, compaction builds the index files after data import.
We recommend using serverless computing resources to perform batch imports. These resources complete compaction and build the full-text inverted index synchronously during data import. For more information, see Use serverless computing to perform read and write tasks and Use serverless computing to perform compaction tasks.
If you do not use serverless resources, we recommend manually triggering compaction after a batch import or index modification by running the following command. For more information, see Compaction (Beta).
VACUUM <schema_name>.<table_name>;
Alter an index
Syntax
-- Modify index configuration
ALTER INDEX [ IF EXISTS ] <idx_name> SET ( <storage_parameter> = '<storage_value>' [ , ... ] );
-- Reset to default configuration
ALTER INDEX [ IF EXISTS ] <idx_name> RESET ( <storage_parameter> [ , ... ] );Parameters
For detailed parameter descriptions, see Parameters.
Examples
After you alter a full-text inverted index, compaction asynchronously builds the index files. We recommend manually triggering compaction after altering an index by running the VACUUM <schema_name>.<table_name>; command. For more information, see Compaction.
Change the index's tokenizer to
standard.ALTER INDEX idx1 SET (tokenizer = 'standard');Change the index's tokenizer to
ikinik_max_wordmode, without converting to lowercase and without any filters.ALTER INDEX idx1 SET ( tokenizer = 'ik', analyzer_params = '{"tokenizer":{"type":"ik","mode":"ik_max_word","enable_lowercase": false}}' );Reset to the default
jiebatokenizer and use its defaultanalyzer_paramsconfiguration.ALTER INDEX idx1 RESET (tokenizer); ALTER INDEX idx1 RESET (tokenizer, analyzer_params);Reset to the default
analyzer_paramsconfiguration for the current tokenizer.ALTER INDEX idx1 RESET (analyzer_params);Change the index's
index_optionstodocs.ALTER INDEX idx1 SET (index_options = 'docs');Reset
index_optionsto its default value,positions.ALTER INDEX idx1 RESET (index_options);
Drop an index
Syntax
DROP INDEX [ IF EXISTS ] <idx_name> [ RESTRICT ];Parameters
For detailed parameter descriptions, see Parameters.
View indexes
Hologres provides the hologres.hg_index_properties system table, where you can view the full-text inverted indexes created for a table and their corresponding positions.
SELECT * FROM hologres.hg_index_properties;Run the following SQL statement to view the table and column associated with an index.
SELECT
t.relname AS table_name,
a.attname AS column_name
FROM pg_class t
JOIN pg_index i ON t.oid = i.indrelid
JOIN pg_class idx ON i.indexrelid = idx.oid
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)
WHERE t.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = '<namespace>')
AND idx.relname = '<indexname>'
LIMIT 1;Parameters:
namespace: The value of the
table_namespacefield in the output of theSELECT * FROM hologres.hg_index_properties;command.indexname: The actual name of the index.
View index build progress
After you create a full-text inverted index, you can use the built-in function hg_show_build_index_progress to view the build progress of the index in real time. This function returns the build status of all full-text indexes on the specified table.
Example
SELECT * FROM hg_show_build_index_progress('<table_name>');Usage notes
To call this function, you must have the SELECT permission on the specified table.
The function returns build information for all full-text indexes on the table, including the number of built files, the total number of files, the build progress in percent, and the estimated remaining time.
Return values
The result includes the following fields:
Field | Data type | Description |
schema_name | TEXT | The name of the schema that contains the index. |
table_name | TEXT | The name of the table. |
index_name | TEXT | The name of the index. |
index_id | BIGINT | The unique ID of the index. |
am_name | TEXT | The type of the index. |
built_index_size | TEXT | The size of the index that has been built. |
built_num_files | INTEGER | The number of files for which index building is complete. |
target_num_files | INTEGER | The total number of files for which the index needs to be built. |
progress | TEXT | The build progress, as a percentage. |
estimated_remaining_time | TEXT | The estimated remaining build time. |
Full-text search using an index
Hologres supports a variety of search modes, enabling you to tailor full-text searches to your business logic.
Search mode | Description |
Keyword match | Searches for keywords in a tokenized search object. You can define the relationship between keywords by using AND/OR logic. |
Phrase search | Searches for a complete phrase. A match requires the words in the phrase to appear within a specified distance of each other. |
Natural language search | Lets you define complex query conditions using natural language syntax. This includes specifying AND/OR logic, required terms, excluded terms, and phrases. |
Term search | Performs an exact match for the search object. The index must contain the exact query string to return a match. |
TEXT_SEARCH function
The TEXT_SEARCH function calculates the BM25 relevance score for a search source based on a search object.
Function syntax
TEXT_SEARCH (
<search_data> TEXT/VARCHAR/CHAR
,<search_expression> TEXT
[ ,<mode> TEXT DEFAULT 'match'
,<operator> TEXT DEFAULT 'OR'
,<tokenizer> TEXT DEFAULT ''
,<analyzer_params> TEXT DEFAULT ''
,<options> TEXT DEFAULT '']
)Parameters
Parameter | Required | Description |
search_data | Yes | The search source. Supported data types are |
search_expression | Yes | The search object. Supported data types are |
mode | No | The search mode. The following modes are supported:
|
operator | No | Specifies the logical operator to use between keywords. This parameter takes effect only when mode is set to
|
tokenizer, analyzer_params | No | Specifies the tokenizer and its configuration for the search_expression. In most cases, you do not need to configure these parameters.
|
options | No | Other parameters for full-text search. The format for the input parameters is
Note The slop parameter represents the maximum allowed interval (or transformation cost) between the words in a phrase. For tokenizers like |
Return value
Returns a non-negative FLOAT value that represents the BM25 relevance score between the search source and the search object. A higher score indicates a higher relevance. The score is 0 if the text is completely irrelevant.
Examples
Use the keyword match mode and change the operator to
AND.-- It is recommended to specify parameter names. SELECT TEXT_SEARCH (content, 'machine learning', operator => 'AND') FROM tbl; -- If you do not specify parameter names, you must provide them in the correct order. SELECT TEXT_SEARCH (content, 'machine learning', 'match', 'AND') FROM tbl;Use the phrase search mode and set
slopto 2.SELECT TEXT_SEARCH (content, 'machine learning', 'phrase', options => 'slop=2;') FROM tbl;Use the natural language search mode.
-- Use the AND and OR operators to define search logic for the tokens. SELECT TEXT_SEARCH (content, 'machine AND (system OR recognition)', 'natural_language') FROM tbl; -- Use + (required term) and - (excluded term) to define search logic for the tokens. SELECT TEXT_SEARCH (content, '+learning -machine system', 'natural_language') FROM tbl;Use the term search mode.
SELECT TEXT_SEARCH (content, 'machine learning', 'term') FROM tbl;Use the fuzzy search mode with
fuzzinessset to 1.SELECT TEXT_SEARCH (content, 'machine learning', 'fuzzy', options => 'fuzziness=1;') FROM tbl;
TOKENIZE function
The TOKENIZE function returns the results of tokenization based on the tokenizer configuration. You can use this function to debug the tokenization of a full-text inverted index.
Function syntax
TOKENIZE (
<search_data> TEXT
[ ,<tokenizer> TEXT DEFAULT ''
,<analyzer_params> TEXT DEFAULT '']
)Parameters
search_data: Required. The target text to tokenize. This parameter must be a constant.
tokenizer, analyzer_params: Optional. Specifies the tokenizer and its configuration for the search_data text. The default tokenizer is
jieba.
Return value
Returns a TEXT array containing the tokens from the target text.
Verify index usage
You can check the execution plan to see if an SQL query uses the full-text inverted index. The presence of Fulltext Filter in the plan indicates that the index is used successfully. For more information about execution plans, see EXPLAIN and EXPLAIN ANALYZE.
Example SQL:
EXPLAIN ANALYZE SELECT * FROM wiki_articles WHERE text_search(content, 'Yangtze River') > 0;The execution plan is as follows. It contains the Fulltext Filter field, which indicates that the SQL statement has successfully used the full-text inverted index.
QUERY PLAN
Gather (cost=0.00..1.00 rows=1 width=12)
-> Local Gather (cost=0.00..1.00 rows=1 width=12)
-> Index Scan using Clustering_index on wiki_articles (cost=0.00..1.00 rows=1 width=12)
Fulltext Filter: (text_search(content, search_expression => 'Yangtze River'::text, mode => match, operator => OR, tokenizer => jieba, analyzer_params => {"filter":["removepunct","lowercase",{"stop_words":["_english_"],"type":"stop"},{"language":"english","type":"stemmer"}],"tokenizer":{"hmm":true,"mode":"search","type":"jieba"}}, options => ) > '0'::double precision)
Query Queue: init_warehouse.default_queue
Optimizer: HQO version 4.0.0Recommendations
Rebuild indexes using Serverless resources
Some property changes trigger compaction and index rebuilding, which can spike CPU usage. Handle these changes as follows:
Changes to `bitmap_columns`, `dictionary_encoding_columns`, or vector indexes
Use the REBUILD syntax with Serverless Computing resources instead of ALTER TABLE ... SET. For more information, see REBUILD.
ASYNC REBUILD TABLE <table_name>
WITH (
rebuild_guc_hg_computing_resource = 'serverless'
)
SET (
bitmap_columns = '<col1>,<col2>',
dictionary_encoding_columns = '<col1>:on,<col2>:off',
vectors = '{
"<col_vector>": {
"algorithm": "HGraph",
"distance_method": "Cosine",
"builder_params": {
"base_quantization_type": "rabitq",
"graph_storage_type": "compressed",
"max_degree": 64,
"ef_construction": 400,
"precise_quantization_type": "fp32",
"use_reorder": true,
"max_total_size_to_merge_mb": 4096
}
}
}'
);Changes to columnar storage for JSON data or full-text index columns
The REBUILD syntax is not yet supported for these changes. Use a temporary table instead:
BEGIN;
-- Clean up any existing temporary table
DROP TABLE IF EXISTS <table_new>;
-- Create a temporary table with the same structure
SET hg_experimental_enable_create_table_like_properties = on;
CALL HG_CREATE_TABLE_LIKE ('<table_new>', 'select * from <table>');
COMMIT;
-- Apply the new column properties to the temporary table
ALTER TABLE <table_new> ALTER COLUMN <column_name> SET (enable_columnar_type = ON);
CREATE INDEX <idx_name> ON <table_new> USING FULLTEXT (column_name);
-- Insert data using Serverless resources (index building completes synchronously)
SET hg_computing_resource = 'serverless';
INSERT INTO <table_new> SELECT * FROM <table>;
ANALYZE <table_new>;
BEGIN;
-- Replace the original table with the temporary table
DROP TABLE IF EXISTS <table>;
ALTER TABLE <table_new> RENAME TO <table>;
COMMIT;Other property changes (e.g., `distribution_key`, `clustering_key`, `segment_key`, storage format)
Use the REBUILD syntax with Serverless Computing resources.
Advanced operations: Customize tokenizer configurations
Hologres recommends using the default tokenizer configuration. However, if the default configuration for a full-text inverted index does not meet your needs, you can customize the tokenizer for more flexible tokenization.
analyzer_params requirements
The analyzer_params parameter must meet the following requirements:
Must be a JSON string.
The top-level JSON object supports two keys:
tokenizerandfilter. They are configured as follows:filter: Optional. A JSON array used to configure filters. Multiple filters are applied in their specified order.tokenizer: Required. A JSON object that configures tokenizer properties. This JSON object supports the following keys:type: Required. The name of the tokenizer.The parameters for the
tokenizerobject vary by tokenizer. For details, see the following table:Tokenizer
Parameter
Description
Value
jieba
mode
The tokenization mode.
search(default): Lists multiple possible token combinations, allowing for redundancy.exact: Does not perform redundant splitting.
hmm
Determines whether to use a Hidden Markov Model to identify words not in the dictionary. This feature improves new word identification.
true(default): Uses the model.false: Does not use the model.
standard
max_token_length
The maximum token length.
A positive integer. The default value is 255. If a token exceeds this length, it is split at intervals of
max_token_length.ik
mode
The tokenization mode.
ik_max_word (default): Fine-grained tokenization that outputs all possible short words.
ik_smart: A coarse-grained tokenization mode that prioritizes longer words to reduce the number of tokens. The output tokens do not overlap. This mode attempts to combine numerals and measure words into a single token.
enable_lowercase
Determines whether to convert tokens to lowercase.
true(default)false
ngram
min_ngram
The minimum character length of a token.
A positive number. The default is 1. The maximum allowed difference from
max_ngramis 3.Note: You can adjust the maximum difference by setting the following GUC, for example,
SET hg_fulltext_index_max_ngram_diff = 5;max_ngram
The maximum character length of a token.
A positive number. The default is 2. The value must be in the range [1, 255]. The maximum allowed difference from
min_ngramis 3.NoteA large difference between
max_ngramandmin_ngramcauses the ngram tokenizer to generate many tokens, increasing resource consumption, storage, and index build time.prefix_only
Determines whether to generate only prefix n-grams.
truefalse(default)
pinyin
keep_first_letter
Determines whether to keep the first letter of each Chinese character.
true(default): Retains the pinyin initials.false: Do not keep the first letter.
keep_separate_first_letter
Determines whether to keep the first letter of each Chinese character as a separate token.
true: Retains the initial of each character.
false(default): Do not keep as separate tokens.
limit_first_letter_length
The maximum length of the token that contains the combined first letters.
An integer. The default value is 16.
keep_full_pinyin
Determines whether to keep the full Pinyin of each Chinese character.
true (default): The pinyin is retained.
false: Do not keep the full Pinyin.
keep_joined_full_pinyin
Determines whether to join the full Pinyin of each Chinese character into a single token.
true: Enables concatenation.
false(default): Do not join the Pinyin.
keep_none_chinese
Determines whether to keep non-Chinese letters or numbers in the result.
true(default): Keeps them.false: Does not keep them.
keep_none_chinese_together
Determines whether to keep consecutive non-Chinese letters or numbers together as a single token.
true(default): Keeps letter and digit sequences together.false: Does not preserve the original form.
NoteThis parameter takes effect only when
keep_none_chineseis set totrue.keep_none_chinese_in_first_letter
Determines whether to keep non-Chinese letters or numbers in the first-letter token.
true (default): Retains the token.
false: Does not keep them.
keep_none_chinese_in_joined_full_pinyin
Determines whether to keep non-Chinese letters or numbers in the joined full Pinyin token.
true: Retains the token.
false(default): Does not keep them.
none_chinese_pinyin_tokenize
Determines whether to split non-Chinese letters into separate Pinyin terms if they form valid Pinyin.
true(default): Split them.false: Do not split them.
NoteThis parameter takes effect only when
keep_none_chineseandkeep_none_chinese_togetherare set totrue.keep_original
Determines whether to keep the original input.
true: Keeps the original input.false(default): Does not keep the original input.
lowercase
Determines whether to convert non-Chinese letters to lowercase.
true(default)false
trim_whitespace
Determines whether to trim whitespace characters.
true(default)false
remove_duplicated_term
Determines whether to remove duplicate terms.
true: Removes stop words.false(default): Do not remove duplicates.
keep_separate_chinese
Determines whether to keep individual Chinese characters as separate tokens.
true: Retains the characters.
false(default): Does not keep them.
Default analyzer_params
The following table shows the default analyzer_params configuration for different tokenizers.
Tokenizer | Default |
jieba (default tokenizer) | |
whitespace | |
keyword | |
simple | |
standard | |
icu | |
ik | |
ngram | |
pinyin | |
filter configuration
Hologres supports the following filters in analyzer_params.
Multiple filters are applied in their specified order.
Filter | Description | Parameter format | Usage example |
lowercase | Converts uppercase letters in a token to lowercase. | Use the filter name as a string. |
|
stop | Removes stop word tokens. |
|
|
stemmer | Reduces tokens to their root form (stem) based on the grammatical rules of a specified language. |
|
|
length | Removes tokens that exceed a specified length. |
|
|
removepunct | Removes tokens that consist only of punctuation characters. | Use the filter name as a string. Note Starting from V4.0.8,
|
|
pinyin | Provides Pinyin-specific token filtering. | | It uses the same properties as the Pinyin tokenizer. |