Tous les produits
Search
Centre de documentation

Tablestore:Tri et pagination

Dernière mise à jour :Aug 18, 2026

Lorsque vous interrogez des données à partir d'un index de recherche, vous pouvez trier les résultats en définissant un ordre au préalable ou en le spécifiant au moment de la requête. Pour les grands ensembles de résultats, utilisez la pagination par décalage ou par jeton afin de trouver rapidement les données dont vous avez besoin.

Cas d'utilisation

Catégorie

Méthode

Fonctionnalité

Cas d'utilisation

Tri

Définir lors de la création

Pré-tri d'index (IndexSort)

Par défaut, Tablestore trie les données dans un index de recherche à l'aide de la méthode de pré-tri d'index configurée (IndexSort). Cela définit l'ordre de tri par défaut pour les résultats renvoyés.

Définir au moment de la requête

ScoreSort (tri par score de pertinence)

Trie les résultats de requête par score de pertinence, calculé à l'aide de l'algorithme BM25. Cette méthode convient aux scénarios basés sur la pertinence, tels que la recherche en texte intégral.

PrimaryKeySort (tri par clé primaire)

Trie les résultats par clé primaire. Cette approche est utile pour classer les éléments selon leurs identifiants uniques.

FieldSort (tri par champ)

Trie les résultats par valeur de champ. Cette fonctionnalité s'avère pratique pour les scénarios de commerce électronique ou de réseaux sociaux où vous souhaitez trier selon des attributs tels que le volume des ventes ou le nombre de pages vues.

Pour les champs multivalués, tels que les champs de type tableau ou de type imbriqué, vous pouvez utiliser le paramètre mode pour contrôler l'élément à utiliser pour le tri.

GeoDistanceSort (tri par distance géographique)

Trie les résultats en fonction de la distance par rapport à un point géographique. Cette option est adaptée aux services basés sur la localisation, comme les cartes ou la logistique, par exemple pour classer les restaurants à proximité par distance.

Pagination

Définir au moment de la requête

Utiliser la pagination par décalage

Utilisez la pagination par décalage lorsque le nombre total de lignes à récupérer est inférieur à 100 000.

Utiliser la pagination par jeton

Recourez à la pagination par jeton pour récupérer séquentiellement de grands ensembles de résultats. Par défaut, vous ne pouvez avancer que vers l'avant. Toutefois, comme un jeton reste valide tout au long du processus de requête, vous pouvez mettre en cache un jeton précédent pour revenir en arrière.

SDK

Vous pouvez implémenter le tri et la pagination à l'aide des SDK pour les langages suivants.

Pré-tri d'index

Par défaut, Tablestore trie les données dans un index de recherche selon un ordre prédéfini, appelé pré-tri d'index (IndexSort). Lorsque vous interrogez des données, IndexSort détermine l'ordre par défaut des résultats renvoyés.

Lors de la création d'un index de recherche, vous pouvez personnaliser IndexSort. Si vous ne spécifiez pas ce paramètre, l'index utilise par défaut le tri par clé primaire.

Important
  • Le pré-tri d'index prend uniquement en charge PrimaryKeySort (tri par clé primaire) et FieldSort (tri par champ).

  • Vous ne pouvez pas utiliser le pré-tri d'index pour un index de recherche contenant des champs de type imbriqué.

  • Après avoir créé un index de recherche, la fonctionnalité de modification dynamique du schéma vous permet de modifier les paramètres IndexSort.

Tri au moment de la requête

Vous ne pouvez trier que sur les champs dont la propriété enableSortAndAgg est définie sur true.

Spécifiez une méthode de tri pour chaque requête. Un index de recherche prend en charge les quatre types de trieurs suivants. Vous pouvez également combiner plusieurs trieurs pour classer les résultats selon une séquence de critères.

ScoreSort

Trie les résultats de requête par score de pertinence, calculé à l'aide de l'algorithme BM25. Cette méthode convient aux scénarios basés sur la pertinence, tels que la recherche en texte intégral.

Important
  • Si vous souhaitez trier par score de pertinence, vous devez spécifier explicitement ScoreSort. Sinon, Tablestore trie les résultats selon les paramètres IndexSort de l'index.

  • Lorsque vous utilisez ScoreSort, les champs de type FuzzyKeyword ne sont pas inclus dans le tri et le paramètre weight n'a aucun effet sur ces champs.

SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(new ScoreSort())));

PrimaryKeySort

Trie les résultats par clé primaire.

SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(new PrimaryKeySort()))); // In ascending order.
//searchQuery.setSort(new Sort(Arrays.asList(new PrimaryKeySort(SortOrder.DESC)))); // In descending order.

FieldSort

Trie les résultats par valeur de champ.

Tri sur un seul champ

Trie les résultats en fonction des valeurs d'un seul champ.

SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(new FieldSort("col", SortOrder.ASC))));

Tri sur plusieurs champs

Trie d'abord les résultats selon les valeurs d'un champ, puis selon celles d'un autre champ.

SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(
    new FieldSort("col1", SortOrder.ASC), new FieldSort("col2", SortOrder.ASC))));

Champ de secours

Lorsque vous triez par un champ de type Long, Double ou Date, vous pouvez définir le paramètre missingField. Ce paramètre spécifie un autre champ du même type à utiliser comme valeur de remplacement pour le tri si une ligne ne contient pas de valeur dans le champ de tri principal.

/**
* Sort results in descending order based on the values in the Col_Long field. 
* If a row is missing a value in the Col_Long field (Long type), 
* the value from the Col_Long_sec field (Long type) is used for sorting instead.
*/
SearchQuery searchQuery = new SearchQuery();
FieldSort fieldSort = new FieldSort("Col_Long");
// Specify the Col_Long_sec field as the fallback for sorting when a value is missing in the Col_Long field.
fieldSort.setMissingField("Col_Long_sec");
fieldSort.setOrder(SortOrder.DESC); 

Valeurs manquantes

Le paramètre missingValue spécifie la position de tri des documents auxquels il manque le champ de tri. Vous pouvez définir ce paramètre pour contrôler l'emplacement de ces documents dans les résultats.

Le comportement de tri est le suivant :

  • Si vous définissez missingValue sur FieldSort.FIRST_WHEN_MISSING, les documents avec des valeurs manquantes sont toujours placés au début des résultats, quel que soit l'ordre de tri (croissant ou décroissant).

  • Si vous définissez missingValue sur FieldSort.LAST_WHEN_MISSING ou null, les documents avec des valeurs manquantes sont toujours placés à la fin des résultats, quel que soit l'ordre de tri.

    /**
    * Sort results in descending order based on the values in the Col_Long field (Long type).
    * If a row is missing a value in the Col_Long field, place that document at the beginning of the results.
    */
    SearchQuery searchQuery = new SearchQuery();
    FieldSort fieldSort = new FieldSort("Col_Long");
    // Place documents with missing values first.
    fieldSort.setMissingValue(FieldSort.FIRST_WHEN_MISSING);
    fieldSort.setOrder(SortOrder.DESC);
    searchQuery.setSort(new Sort(Arrays.asList(fieldSort)));

Champs multivalués

Pour les champs multivalués, tels que les champs de type tableau ou de type imbriqué, vous pouvez utiliser le paramètre mode pour spécifier l'élément à utiliser pour le tri.

Tri par une valeur spécifiée dans un tableau multivalué.

// Assume you have two rows, doc1 and doc2. Both have a field1 of array type.
// The value of field1 in doc1 is [2,3]. The value of field1 in doc2 is [1,3,4].
// You can set the mode parameter to specify which value in the array to use for sorting.
{
    // When mode is set to SortMode.MAX, the sort order is doc2 (sorted by 4), then doc1 (sorted by 3).
    FieldSort fieldSort = new FieldSort("field1", SortOrder.DESC);
    fieldSort.setMode(SortMode.MAX);
}
{
    // When mode is set to SortMode.MIN, the sort order is doc1 (sorted by 2), then doc2 (sorted by 1).
    FieldSort fieldSort = new FieldSort("field1", SortOrder.DESC);
    fieldSort.setMode(SortMode.MIN);
}

Vous pouvez également trier les sous-lignes d'un champ de type imbriqué.

// Assume you have two rows, doc1 and doc2. Both have a field1 of nested type.
// The value of field1 in doc1 is [{"name":"b", "age":1},{"name":"a", "age":7}].
// The value of field1 in doc2 is [{"name":"a", "age":1},{"name":"c", "age":1},{"name":"d", "age":5}].

{
    // Sort all sub-rows and use the mode parameter to specify which value to use for sorting.
    // When mode is set to SortMode.MAX and you sort by the age field, the result is doc1 (sorted by 7), then doc2 (sorted by 5).
    FieldSort fieldSort = new FieldSort("field1.age", SortOrder.DESC);
    fieldSort.setMode(SortMode.MAX);
    String path = "field1";
    NestedFilter nestedFilter = new NestedFilter(path, QueryBuilders.matchAll().build());
    fieldSort.setNestedFilter(nestedFilter);
}
{
    // Sort only the sub-rows where age=1, and use the mode parameter to specify which value to use.
    {
        // When mode is set to SortMode.MAX and you sort by the name field, the result is doc2 (sorted by "c"), then doc1 (sorted by "b").
        FieldSort fieldSort = new FieldSort("field1.name", SortOrder.DESC);
        fieldSort.setMode(SortMode.MAX);
        String path = "field1";
        NestedFilter nestedFilter = new NestedFilter(path, QueryBuilders.term("field1.age",1).build());
        fieldSort.setNestedFilter(nestedFilter);
    }
    {
        // When mode is set to SortMode.MIN and you sort by the name field, the result is doc1 (sorted by "b"), then doc2 (sorted by "a").
        FieldSort fieldSort = new FieldSort("field1.name", SortOrder.DESC);
        fieldSort.setMode(SortMode.MIN);
        String path = "field1";
        NestedFilter nestedFilter = new NestedFilter(path, QueryBuilders.term("field1.age",1).build());
        fieldSort.setNestedFilter(nestedFilter);
    }
}

GeoDistanceSort

Trie les résultats en fonction de la distance par rapport à un point géographique.

SearchQuery searchQuery = new SearchQuery();
// The 'geo' field is of the GeoPoint type. Sort results by the distance
// from the value in this field to the point "0,0".
Sort.Sorter sorter = new GeoDistanceSort("geo", Arrays.asList("0, 0"));
searchQuery.setSort(new Sort(Arrays.asList(sorter)));

Méthodes de pagination

Pour paginer les résultats de requête, vous pouvez utiliser les paramètres limit et offset ou un jeton.

Pagination par décalage

Utilisez la pagination par décalage lorsque le nombre total de lignes à récupérer est inférieur à 100 000. La somme de limit et de offset doit être inférieure ou égale à 100 000, et la valeur maximale pour limit est de 100.

Remarque

Pour augmenter le seuil limit, consultez la rubrique Comment augmenter la limite de l'API Search à 1 000 ?.

Si vous ne définissez pas les paramètres limit et offset, limit prend par défaut la valeur 10 et offset prend par défaut la valeur 0.

SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(new MatchAllQuery());
searchQuery.setLimit(100);
searchQuery.setOffset(100);

Pagination par jeton

La pagination par jeton est recommandée pour la pagination profonde car elle n'impose aucune limite de profondeur.

Si une réponse ne contient pas toutes les données correspondantes, le serveur renvoie un nextToken.

Par défaut, la pagination par jeton vous permet uniquement d'avancer dans les résultats. Toutefois, comme un jeton reste valide tout au long du processus de requête, vous pouvez mettre en cache un jeton précédent pour revenir en arrière.

Important

Si vous devez persister un nextToken ou l'envoyer à une application frontale, encodez-le en chaîne à l'aide de Base64. Un jeton est un tableau d'octets, pas une chaîne. Le convertir directement en chaîne avec new String(nextToken) entraîne une perte de données.

Lorsque vous paginez avec un jeton, l'ordre de tri reste identique à celui de la requête précédente, qu'il utilise le IndexSort par défaut ou un tri personnalisé. Par conséquent, vous ne pouvez pas définir de paramètre Sort lorsqu'un jeton est utilisé. Vous ne pouvez pas non plus définir de offset, car vous ne pouvez lire les données que de manière séquentielle.

Important

Un index de recherche contenant un champ de type imbriqué ne prend pas en charge le pré-tri d'index. Si vous devez paginer les résultats d'un tel index, vous devez spécifier un ordre de tri dans la requête. Sinon, le serveur ne renvoie pas de nextToken même si d'autres données sont disponibles.

private static void readMoreRowsWithToken(SyncClient client) {
    SearchQuery searchQuery = new SearchQuery();
    searchQuery.setQuery(new MatchAllQuery());
    searchQuery.setGetTotalCount(true);// Set to return the total count of matched rows.
    // Specify the data table name (for example, sampleTable) and the search index name (for example, sampleSearchIndex). 
    // You can find the search index name on the Index Management tab for the table in the Tablestore console, or by listing search indexes with the SDK.
    SearchRequest searchRequest = new SearchRequest("sampleTable", "sampleSearchIndex", searchQuery);

    SearchResponse resp = client.search(searchRequest);
    if (!resp.isAllSuccess()) {
        throw new RuntimeException("not all success");
    }
    List<Row> rows = resp.getRows();
    while (resp.getNextToken()!=null) { // A null nextToken means all data has been read.
        // Get the nextToken.
        byte[] nextToken = resp.getNextToken();

        {
            // If you need to persist the nextToken or send it to a front-end application, 
            // use Base64 to encode the nextToken into a string for storage and transfer.
            // A token is a byte array. Directly using new String(nextToken) will cause data loss.
            String tokenAsString = Base64.toBase64String(nextToken);
            // Decode the string back to a byte array.
            byte[] tokenAsByte = Base64.fromBase64String(tokenAsString);
        }

        // Set the token for the next request.
        searchRequest.getSearchQuery().setToken(nextToken);
        resp = client.search(searchRequest);
        if (!resp.isAllSuccess()) {
            throw new RuntimeException("not all success");
        }
        rows.addAll(resp.getRows());
    }
    System.out.println("RowSize: " + rows.size());
    System.out.println("TotalCount: " + resp.getTotalCount());// Prints the total number of matched rows, not the number of returned rows.
}