All Products
Search
Document Center

Tablestore:Token-based wildcard query

Last Updated:Sep 10, 2026

Dalam skenario kueri wildcard (*word*), Anda dapat menggabungkan tokenisasi fuzzy dan permintaan pencocokan frasa untuk menjalankan kueri fuzzy berkinerja tinggi.

Informasi latar belakang

Kueri fuzzy merupakan kebutuhan umum dalam operasi database, seperti menanyakan nama file atau nomor ponsel. Untuk menjalankan kueri fuzzy di Tablestore, Anda dapat menggunakan kueri wildcard pada indeks pencarian, yang mirip dengan fungsi LIKE di MySQL. Namun, kueri wildcard memiliki keterbatasan: panjang kueri pencarian tidak boleh melebihi 32 karakter, dan kinerjanya menurun seiring peningkatan volume data.

Untuk mengatasi masalah ini, indeks pencarian mendukung kueri wildcard berbasis token guna meningkatkan kinerja kueri fuzzy. Saat menggunakan kueri wildcard berbasis token, tidak ada batasan panjang kueri pencarian. Namun, konten asli dibatasi hingga maksimal 1.024 karakter. Konten yang melebihi batas ini akan dipotong, dan hanya 1.024 karakter pertama yang dipertahankan.

Skenario

Pilih metode yang sesuai untuk menjalankan kueri fuzzy berdasarkan skenario Anda.

  • Untuk skenario kueri wildcard yang menggunakan pola *word*, Anda dapat menggunakan kueri wildcard berbasis token. Misalnya, metode ini dapat digunakan untuk mencari nomor ponsel yang mengandung 123 di posisi mana pun dengan melakukan pencarian "123".

    Dalam kebanyakan kasus, metode ini meningkatkan kinerja lebih dari 10 kali lipat dibandingkan kueri wildcard standar.

    Asumsikan sebuah tabel data berisi kolom file_name. Di indeks pencarian, kolom ini bertipe Text, dan alat analisis (analyzer) diatur ke Fuzzy Analyzer. Untuk menemukan baris tempat nilai kolom file_name adalah 2021 woRK@Hangzhou, Anda harus menggunakan permintaan pencocokan frasa (MatchPhraseQuery). Kueri pencarian harus berupa substring berurutan dari teks asli.

    • Jika kueri pencarian adalah 2021, 20, 21, work, WORK, @, Hang, zhou, Hangzhou, atau @Hangzhou, kueri tersebut akan cocok dengan baris tempat nilai kolom file_name adalah 2021 woRK@Hangzhou.

    • Jika kueri pencarian adalah 21work, 2021Hangzhou, 2120, atau #Hangzhou, kueri tersebut tidak akan cocok dengan baris tempat nilai kolom file_name adalah 2021 woRK@Hangzhou.

  • Untuk skenario kueri kompleks lainnya, Anda dapat menggunakan kueri wildcard untuk menjalankan kueri fuzzy. Untuk informasi selengkapnya, lihat Wildcard query.

Penggunaan

Ikuti langkah-langkah berikut untuk menjalankan kueri fuzzy menggunakan metode berbasis token:

  1. Saat membuat indeks pencarian, atur tipe kolom menjadi Text dan analyzer menjadi Fuzzy Analyzer. Anda dapat menggunakan konfigurasi default untuk parameter lainnya. Untuk informasi selengkapnya, lihat Create a search index.

    Catatan

    Jika indeks pencarian sudah ada, Anda dapat menggunakan fitur modifikasi skema dinamis untuk menambahkan kolom virtual pada kolom tertentu. Atur tipe kolom virtual menjadi Text dan analyzer menjadi Fuzzy Analyzer. Untuk informasi selengkapnya, lihat Dynamically modify a schema dan Virtual columns.

  2. Saat menanyakan data menggunakan indeks pencarian, gunakan MatchPhraseQuery. Untuk informasi selengkapnya, lihat Match phrase query.

Lampiran: Studi kasus

Contoh berikut menunjukkan cara menggunakan kueri wildcard berbasis token untuk menjalankan kueri 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 {
        // Definisikan skema tabel.
        IndexSchema indexSchema = new IndexSchema();
        indexSchema.setFieldSchemas(Collections.singletonList(
                // Catatan: Jika bidang name awalnya bertipe Keyword, kueri mungkin gagal setelah Anda mengubah tipe bidang menjadi Text dan mengonfigurasi analyzer.
                // Untuk mempertahankan kedua tipe Keyword dan Text, lihat contoh fitur kolom virtual. Jika Anda hanya perlu menggunakan bidang name untuk menjalankan kueri yang cocok dengan *abc*, cukup gunakan bidang bertipe Text saja. Tipe Keyword tidak diperlukan.
                new FieldSchema("name", FieldType.TEXT).setAnalyzer(FieldSchema.Analyzer.Fuzzy)
        ));
        // Buat indeks pencarian.
        {
            CreateSearchIndexRequest request = new CreateSearchIndexRequest();
            request.setTableName(tableName);
            request.setIndexName(indexName);
            request.setIndexSchema(indexSchema);
            CreateSearchIndexResponse response = client.createSearchIndex(request);
        }

        // Tulis satu baris 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);
        // Tulis kolom atribut.
        rowPutChange.addColumn("name", ColumnValue.fromString("Tuner1024x768P.mp4"));
        PutRowRequest request = new PutRowRequest(rowPutChange);
        client.putRow(request);

        // Tunggu hingga data disinkronkan ke indeks pencarian.
        Thread.sleep(1000 * 180);

        // Demonstrasi fitur kueri yang cocok dengan *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);
    }

    // Gunakan kolom virtual.
    public void testFuzzyMatchPhraseWithVirtualField(SyncClient client) throws Exception {
        // Definisikan skema tabel.
        IndexSchema indexSchema = new IndexSchema();
        indexSchema.setFieldSchemas(Arrays.asList(
                // Bidang sumber bertipe Keyword, yang memudahkan kueri pencocokan eksak.
                new FieldSchema("name", FieldType.KEYWORD).setIndex(true).setStore(true),
                // Buat kolom virtual bernama name_virtual_text. Atur tipe kolom virtual menjadi Text dan analyzer menjadi Fuzzy. Sumber kolom virtual ini adalah bidang name.
                new FieldSchema("name_virtual_text", FieldType.TEXT).setIndex(true).setAnalyzer(FieldSchema.Analyzer.Fuzzy).setVirtualField(true).setSourceFieldName("name")
        ));
        // Buat indeks pencarian.
        {
            CreateSearchIndexRequest request = new CreateSearchIndexRequest();
            request.setTableName(tableName);
            request.setIndexName(indexName);
            request.setIndexSchema(indexSchema);
            CreateSearchIndexResponse response = client.createSearchIndex(request);
        }

        // Tulis satu baris 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);
        // Tulis kolom atribut.
        rowPutChange.addColumn("name", ColumnValue.fromString("Tuner1024x768P.mp4"));
        PutRowRequest request = new PutRowRequest(rowPutChange);
        client.putRow(request);

        // Tunggu hingga data disinkronkan ke indeks pencarian.
        Thread.sleep(1000 * 180);

        // Demonstrasi skenario kueri yang cocok dengan *abc*.
        // Perhatikan bahwa bidang kueri adalah kolom virtual name_virtual_text, bukan 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);
    }

    // Tunjukkan cara mengimplementasikan 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();
        // Gunakan MatchPhraseQuery untuk menanyakan bidang yang telah ditokenisasi.
        searchQuery.setQuery(QueryBuilders.matchPhrase(fieldName, searchContent).build());
        searchQuery.setLimit(0);
        // Untuk mendemonstrasikan fitur ini, contoh ini mengembalikan jumlah total baris yang cocok. Jika Anda tidak memerlukan jumlah total, atur nilai ini ke false agar kinerja lebih baik.
        searchQuery.setGetTotalCount(true);
        searchRequest.setSearchQuery(searchQuery);
        SearchResponse response = client.search(searchRequest);
        assertEquals(String.format("field:[%s], searchContent:[%s]", fieldName, searchContent), exceptCount, response.getTotalCount());
    }
}

FAQ

Referensi