Lorsque vous interrogez des données à l'aide d'un index de recherche, vous pouvez contrôler l'ordre des résultats en définissant une méthode de tri au préalable ou en la spécifiant au moment de la requête. Si l'ensemble de résultats est volumineux, utilisez la pagination pour accéder rapidement aux données souhaitées.
IndexSort
Par défaut, un index de recherche trie les données selon la valeur IndexSort configurée. Lorsque vous interrogez des données via cet index, IndexSort détermine l'ordre par défaut des résultats.
Vous pouvez définir une valeur IndexSort personnalisée lors de la création d'un index de recherche. Si vous ne spécifiez pas de valeur personnalisée pour IndexSort, le tri s'effectue par défaut selon la clé primaire.
IndexSortprend uniquement en chargePrimaryKeySort(tri par clé primaire) etFieldSort(tri par valeur de champ).Les index de recherche contenant des champs de type nested ne prennent pas en charge
IndexSort.Après la création d'un index de recherche, vous pouvez utiliser la fonctionnalité de modification dynamique du schéma pour modifier le paramètre
IndexSort.
Tri au moment de la requête
Le tri n'est pris en charge que pour les champs dont le paramètre EnableSortAndAgg est défini sur true.
Vous pouvez spécifier une méthode de tri pour chaque requête. Un index de recherche prend en charge quatre types de trieurs. Vous pouvez également combiner plusieurs trieurs afin d'ordonner les résultats selon une séquence de critères.
ScoreSort
Trie les résultats selon leur score de pertinence, calculé à l'aide de l'algorithme BM25. Cette méthode convient aux scénarios nécessitant un classement par pertinence, tels que la recherche en texte intégral.
Pour trier les résultats par score de pertinence, vous devez spécifier explicitement
ScoreSort. À défaut, les résultats sont triés selon le paramètreIndexSortde l'index.Lorsque vous utilisez
ScoreSort, les champs FuzzyKeyword ne sont pas inclus dans le processus de tri et le paramètreweightn'a aucun effet sur ces champs.
searchQuery := search.NewSearchQuery()
searchQuery.SetSort(&search.Sort{
[]search.Sorter{
&search.ScoreSort{
Order: search.SortOrder_DESC.Enum(), // Sort in descending order of score.
},
},
})
PrimaryKeySort
Trie les résultats selon la clé primaire, ce qui permet d'ordonner les éléments par leurs identifiants uniques.
searchQuery := search.NewSearchQuery()
searchQuery.SetSort(&search.Sort{
[]search.Sorter{
&search.PrimaryKeySort{
Order: search.SortOrder_ASC.Enum(),
},
},
})
FieldSort
Trie les résultats selon la valeur d'un champ spécifique. Cette approche est utile dans les applications de commerce électronique ou les réseaux sociaux, où il peut être nécessaire de classer les articles selon des attributs tels que le volume des ventes ou le nombre de pages vues.
Tri sur une seule colonne
Trie les résultats en fonction des valeurs d'un seul champ.
// Sort the results based on the Col_Long field in descending order.
searchQuery.SetSort(&search.Sort{
[]search.Sorter{
&search.FieldSort{
FieldName: "Col_Long",
Order: search.SortOrder_DESC.Enum(),
},
},
})
Tri multicolumnes
Trie d'abord les résultats selon les valeurs d'un premier champ, puis selon celles d'un second.
searchQuery.SetSort(&search.Sort{
[]search.Sorter{
&search.FieldSort{
FieldName: "col1",
Order: search.SortOrder_ASC.Enum(),
},
&search.FieldSort{
FieldName: "col2",
Order: search.SortOrder_DESC.Enum(),
},
},
})
Tri des valeurs manquantes
Lorsqu'un champ de tri est absent d'un document, le paramètre MissingValue détermine sa position dans les résultats triés.
Le comportement de tri est le suivant :
Si vous définissez
MissingValuesursearch.FirstWhenMissing, les documents ne contenant pas le champ sont placés au début, que l'ordre de tri soit croissant (asc) ou décroissant (desc).-
Si vous définissez
MissingValuesursearch.LastWhenMissingounil, les documents ne contenant pas le champ sont placés à la fin, quel que soit l'ordre de tri.// Sort the results based on the view_at field in ascending order, // and place documents with missing values at the end. searchQuery.SetSort(&search.Sort{ []search.Sorter{ &search.FieldSort{ FieldName: "view_at", Order: search.SortOrder_ASC.Enum(), MissingValue: search.LastWhenMissing, }, }, })
GeoDistanceSort
Trie les résultats selon la distance par rapport à un point géographique. Cette fonctionnalité est utile pour les applications de cartographie et de logistique, par exemple pour classer les restaurants à proximité en fonction de leur distance par rapport à votre position actuelle.
searchQuery.SetSort(&search.Sort{
[]search.Sorter{
&search.GeoDistanceSort{
FieldName: "location", // Specify the name of the GeoPoint field.
Points: []string{"40,-70"}, // Specify the center point.
},
},
})
Méthodes de pagination
Pour paginer les résultats, vous pouvez utiliser soit les paramètres Limit et Offset, soit un jeton.
Pagination avec Limit et Offset
Vous pouvez utiliser Limit et Offset pour la pagination. La somme de Limit et Offset doit être inférieure ou égale à 100 000, et la valeur maximale de Limit est de 100.
Pour augmenter la limite supérieure du paramètre Limit, consultez la rubrique Comment augmenter le paramètre limit à 1000 pour les requêtes d'index de recherche ?.
Si vous ne spécifiez pas ces paramètres, Limit prend par défaut la valeur 10 et Offset prend par défaut la valeur 0.
searchQuery := search.NewSearchQuery()
searchQuery.SetLimit(10)
searchQuery.SetOffset(10)
Pagination avec un jeton
Pour la pagination profonde, utilisez un jeton, car cette méthode n'impose aucune limitation de profondeur.
Si une requête renvoie plus de résultats qu'une seule réponse ne peut en contenir, le serveur fournit un NextToken. Utilisez ce jeton dans une requête suivante pour récupérer la page suivante.
Par défaut, la pagination par jeton permet uniquement d'avancer. Toutefois, comme un jeton reste valide pendant toute la durée d'une session de requête, vous pouvez mettre en cache les jetons précédents pour implémenter une pagination arrière.
Si vous devez persister le NextToken ou l'envoyer à une application frontale, utilisez l'encodage Base64 pour le convertir en chaîne de caractères afin de le stocker et le transmettre. Étant donné que le jeton est un slice d'octets et non une chaîne, une conversion directe via string(NextToken) entraîne une perte de données.
Lorsque vous utilisez un jeton, la méthode de tri de la requête précédente est automatiquement appliquée. Par conséquent, vous ne pouvez pas spécifier les paramètres Sort ou Offset dans une requête basée sur un jeton. Vous pouvez uniquement lire les données de manière séquentielle, page par page.
Les index de recherche contenant des champs de type nested ne prennent pas en charge IndexSort. Par conséquent, vous devez spécifier une méthode de tri dans votre requête pour activer la pagination. Sans ordre de tri spécifié, le serveur ne renverra pas de NextToken, même si d'autres résultats existent.
/**
* Read data page by page by using a token.
* If a SearchResponse contains a NextToken, you can use it to initiate the next query.
* A nil NextToken indicates that all matching data has been retrieved.
*/
func QueryRowsWithToken(client *tablestore.TableStoreClient, tableName string, indexName string) {
querys := []search.Query{
&search.MatchAllQuery{},
&search.TermQuery{
FieldName: "Col_Keyword",
Term: "tablestore",
},
}
for _, query := range querys {
fmt.Printf("Test query: %#v\n", query)
searchRequest := &tablestore.SearchRequest{}
searchRequest.SetTableName(tableName)
searchRequest.SetIndexName(indexName)
searchQuery := search.NewSearchQuery()
searchQuery.SetQuery(query)
searchQuery.SetLimit(10)
searchQuery.SetGetTotalCount(true)
searchRequest.SetSearchQuery(searchQuery)
searchResponse, err := client.Search(searchRequest)
if err != nil {
fmt.Printf("%#v", err)
return
}
rows := searchResponse.Rows
requestCount := 1
for searchResponse.NextToken != nil {
{
// To persist or send the NextToken, Base64-encode it.
// The token is a byte slice, not a string; direct conversion causes data loss.
tokenAsString := base64.StdEncoding.EncodeToString(searchResponse.NextToken)
// Decode the string back into a byte slice.
tokenAsByte, err := base64.StdEncoding.DecodeString(tokenAsString)
if err != nil {
fmt.Printf("len:%d, %#v",len(tokenAsByte), err)
return
}
}
searchQuery.SetToken(searchResponse.NextToken)
searchResponse, err = client.Search(searchRequest)
if err != nil {
fmt.Printf("%#v", err)
return
}
requestCount++
for _, r := range searchResponse.Rows {
rows = append(rows, r)
}
}
fmt.Println("IsAllSuccess: ", searchResponse.IsAllSuccess)
fmt.Println("TotalCount: ", searchResponse.TotalCount)
fmt.Println("RowsSize: ", len(rows))
fmt.Println("RequestCount: ", requestCount)
}
}