Todos os produtos
Search
Central de documentação

Tablestore:Token-based wildcard query

Última atualização: Sep 09, 2026

Em cenários de consulta wildcard (WildcardQuery) com o padrão *word*, combine tokenização fuzzy e consulta de correspondência de frase para executar consultas fuzzy de alto desempenho.

Informações básicas

Consultas fuzzy são comuns em operações de banco de dados, como pesquisas por nomes de arquivos ou números de telefone celular. Para executar consultas fuzzy no Tablestore, use uma consulta wildcard em um search index, funcionalidade semelhante à função LIKE do MySQL. No entanto, as consultas wildcard têm limitações: a string de busca não pode exceder 32 caracteres e o desempenho diminui conforme o volume de dados aumenta.

Para resolver esses problemas, o search index oferece suporte a consultas wildcard baseadas em token, o que melhora significativamente o desempenho das consultas fuzzy. Esse tipo de consulta não impõe limite ao comprimento da string de busca. Contudo, o conteúdo original aceita no máximo 1.024 caracteres. O sistema trunca qualquer conteúdo que ultrapasse esse limite e mantém apenas os primeiros 1.024 caracteres.

Cenários

Escolha o método mais adequado para executar consultas fuzzy conforme o seu cenário.

  • Em cenários de consulta wildcard com o padrão *word*, use a consulta wildcard baseada em token. Por exemplo, ao buscar "123", você encontra números de telefone celular que contêm 123 em qualquer posição.

    Na maioria dos casos, essa abordagem melhora o desempenho em mais de 10 vezes em comparação à consulta wildcard padrão.

    Considere uma tabela de dados com uma coluna file_name. No search index, essa coluna é do tipo Text e o analisador está definido como Fuzzy Analyzer. Para localizar a linha em que o valor da coluna file_name é 2021 woRK@Hangzhou, use uma consulta de correspondência de frase (MatchPhraseQuery). A string de busca deve ser uma substring consecutiva do texto original.

    • A consulta retorna a linha com o valor 2021 woRK@Hangzhou na coluna file_name quando a string de busca for 2021, 20, 21, work, WORK, @, Hang, zhou, Hangzhou ou @Hangzhou.

    • A consulta não retorna a linha com o valor 2021 woRK@Hangzhou na coluna file_name quando a string de busca for 21work, 2021Hangzhou, 2120 ou #Hangzhou.

  • Para outros cenários de consulta complexa, use uma consulta wildcard para executar buscas fuzzy. Para obter mais informações, consulte Wildcard query.

Uso

Siga estas etapas para executar uma consulta fuzzy com o método baseado em token:

  1. Ao criar um search index, defina o tipo da coluna como Text e o analisador como Fuzzy Analyzer. Mantenha as configurações padrão para os demais parâmetros. Para obter mais informações, consulte Crie um search index.

    Nota

    Se já existir um search index, use o recurso de modificação dinâmica de esquema para adicionar uma coluna virtual à coluna especificada. Defina o tipo da coluna virtual como Text e o analisador como Fuzzy Analyzer. Para obter mais informações, consulte Modifique dinamicamente um esquema e Virtual columns.

  2. Ao consultar dados por meio do search index, use MatchPhraseQuery. Para obter mais informações, consulte Match phrase query.

Apêndice: Caso de uso

O exemplo a seguir demonstra como usar uma consulta wildcard baseada em token para executar uma consulta fuzzy.

import com.alicloud.openservices.tablestore.SyncClient;
import com.alicloud.openservices.tablestore.model.ColumnValue;
import com.alicloud.openservices.tablestore.model.PrimaryKey;
import com.alicloud.openservices.tablestore.model.PrimaryKeyBuilder;
import com.alicloud.openservices.tablestore.model.PrimaryKeyValue;
import com.alicloud.openservices.tablestore.model.PutRowRequest;
import com.alicloud.openservices.tablestore.model.RowPutChange;
import com.alicloud.openservices.tablestore.model.search.CreateSearchIndexRequest;
import com.alicloud.openservices.tablestore.model.search.CreateSearchIndexResponse;
import com.alicloud.openservices.tablestore.model.search.FieldSchema;
import com.alicloud.openservices.tablestore.model.search.FieldType;
import com.alicloud.openservices.tablestore.model.search.IndexSchema;
import com.alicloud.openservices.tablestore.model.search.SearchQuery;
import com.alicloud.openservices.tablestore.model.search.SearchRequest;
import com.alicloud.openservices.tablestore.model.search.SearchResponse;
import com.alicloud.openservices.tablestore.model.search.query.QueryBuilders;

import java.util.Arrays;
import java.util.Collections;

import static org.junit.Assert.assertEquals;

public class TestFuzzy {
    private static final String tableName = "analysis_test";
    private static final String indexName = "analysis_test_index";

    public void testFuzzyMatchPhrase(SyncClient client) throws Exception {
        // Define the table schema.
        IndexSchema indexSchema = new IndexSchema();
        indexSchema.setFieldSchemas(Collections.singletonList(
                // Note: If the name field was originally of the Keyword type, queries may fail after you change the field type to Text and configure an analyzer.
                // To retain both Keyword and Text types, see the example for the virtual column feature. If you only need to use the name field to perform queries that match *abc*, use only the Text type field. The Keyword type is not required.
                new FieldSchema("name", FieldType.TEXT).setAnalyzer(FieldSchema.Analyzer.Fuzzy)
        ));
        // Create a search index.
        {
            CreateSearchIndexRequest request = new CreateSearchIndexRequest();
            request.setTableName(tableName);
            request.setIndexName(indexName);
            request.setIndexSchema(indexSchema);
            CreateSearchIndexResponse response = client.createSearchIndex(request);
        }

        // Write a row of data.
        PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
                .addPrimaryKeyColumn("pk1", PrimaryKeyValue.fromString("1"))
                .addPrimaryKeyColumn("pk2", PrimaryKeyValue.fromLong(1))
                .addPrimaryKeyColumn("pk3", PrimaryKeyValue.fromBinary(new byte[]{1, 2, 3}))
                .build();
        RowPutChange rowPutChange = new RowPutChange(tableName, primaryKey);
        // Write an attribute column.
        rowPutChange.addColumn("name", ColumnValue.fromString("Tuner1024x768P.mp4"));
        PutRowRequest request = new PutRowRequest(rowPutChange);
        client.putRow(request);

        // Wait for the data to be synchronized to the search index.
        Thread.sleep(1000 * 180);

        // Demonstrate the query feature that matches *abc*.
        assertMatchPhraseQuery(client, tableName, indexName, "name", "Tun", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name", "Tuner", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name", "Tun er", 0);
        assertMatchPhraseQuery(client, tableName, indexName, "name", "Tuner102", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name", "Tuner1024", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name", "Tuner1024x", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name", "Tuner1024x7", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name", "Tuner1024x768P.mp4", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name", "24x768P.mp4", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name", "24x76 8P.mp4", 0);
        assertMatchPhraseQuery(client, tableName, indexName, "name", "24x7 P.mp4", 0);
    }

    // Use a virtual column.
    public void testFuzzyMatchPhraseWithVirtualField(SyncClient client) throws Exception {
        // Define the table schema.
        IndexSchema indexSchema = new IndexSchema();
        indexSchema.setFieldSchemas(Arrays.asList(
                // The source field is of the Keyword type, which is convenient for exact match queries.
                new FieldSchema("name", FieldType.KEYWORD).setIndex(true).setStore(true),
                // Create a virtual column named name_virtual_text. Set the type of the virtual column to Text and the analyzer to Fuzzy. The source of this virtual column is the name field.
                new FieldSchema("name_virtual_text", FieldType.TEXT).setIndex(true).setAnalyzer(FieldSchema.Analyzer.Fuzzy).setVirtualField(true).setSourceFieldName("name")
        ));
        // Create a search index.
        {
            CreateSearchIndexRequest request = new CreateSearchIndexRequest();
            request.setTableName(tableName);
            request.setIndexName(indexName);
            request.setIndexSchema(indexSchema);
            CreateSearchIndexResponse response = client.createSearchIndex(request);
        }

        // Write a row of data.
        PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
                .addPrimaryKeyColumn("pk1", PrimaryKeyValue.fromString("1"))
                .addPrimaryKeyColumn("pk2", PrimaryKeyValue.fromLong(1))
                .addPrimaryKeyColumn("pk3", PrimaryKeyValue.fromBinary(new byte[]{1, 2, 3}))
                .build();
        RowPutChange rowPutChange = new RowPutChange(tableName, primaryKey);
        // Write an attribute column.
        rowPutChange.addColumn("name", ColumnValue.fromString("Tuner1024x768P.mp4"));
        PutRowRequest request = new PutRowRequest(rowPutChange);
        client.putRow(request);

        // Wait for the data to be synchronized to the search index.
        Thread.sleep(1000 * 180);

        // Demonstrate the query scenario that matches *abc*.
        // Note that the query field is the virtual column name_virtual_text, not name.
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "Tun", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "Tuner", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "Tun er", 0);
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "Tuner102", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "Tuner1024", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "Tuner1024x", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "Tuner1024x7", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "Tuner1024x768P.mp4", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "24x768P.mp4", 1);
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "24x76 8P.mp4", 0);
        assertMatchPhraseQuery(client, tableName, indexName, "name_virtual_text", "24x7 P.mp4", 0);
    }

    // Show how to implement MatchPhraseQuery.
    public static void assertMatchPhraseQuery(SyncClient client, String tableName, String indexName, String fieldName, String searchContent, long exceptCount) {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.setTableName(tableName);
        searchRequest.setIndexName(indexName);
        SearchQuery searchQuery = new SearchQuery();
        // Use MatchPhraseQuery to query the tokenized field.
        searchQuery.setQuery(QueryBuilders.matchPhrase(fieldName, searchContent).build());
        searchQuery.setLimit(0);
        // To demonstrate the feature, this example returns the total number of matched rows. If you do not need the total count, set this to false for better performance.
        searchQuery.setGetTotalCount(true);
        searchRequest.setSearchQuery(searchQuery);
        SearchResponse response = client.search(searchRequest);
        assertEquals(String.format("field:[%s], searchContent:[%s]", fieldName, searchContent), exceptCount, response.getTotalCount());
    }
}

FAQ

Referências