使用多元索引时,可以在创建时指定索引预排序和在查询时指定排序方式,在获取返回结果时可以使用limit和offset或者使用token进行翻页。

索引预排序(IndexSort)

多元索引默认会按照索引中设置的IndexSort进行排序,IndexSort决定了多元索引查询时默认的返回顺序,默认的IndexSort为主键排序,在创建索引时可以自定义预排序方式。如果未自定义IndexSort,即按照主键顺序返回。

说明 含有Nested类型的索引不支持IndexSort,没有预排序。

查询时指定排序方式

只有enable_sort_and_agg设置为true的字段才能进行排序。

在每次查询时,可以指定排序方式,多元索引支持如下四种排序方式(Sorter)。您也可以使用多个Sorter,实现先按照某种方式排序,再按照另一种方式排序的需求。

  • ScoreSort
    按照查询结果的相关性(BM25算法)分数进行排序,适用于有相关性的场景,例如全文检索等。
    说明 如果需要按照相关性打分进行排序,必须手动设置ScoreSort,否则会按照索引设置的IndexSort进行排序。
    'sort' => array(
        array(
            'score_sort' => array(
                'order' => SortOrderConst::SORT_ORDER_DESC
            )
        ),
    )
  • PrimaryKeySort

    按照主键进行排序。

    'sort' => array(
        array(
            'pk_sort' => array(
                'order' => SortOrderConst::SORT_ORDER_ASC
            )
        ),
    )
  • FieldSort

    按照某列的值进行排序。

    'sort' => array(
        array(
            'field_sort' => array(
                'field_name' => 'keyword',
                'order' => SortOrderConst::SORT_ORDER_ASC,
                'mode' => SortModeConst::SORT_MODE_AVG,
            )
        ),
    )
  • GeoDistanceSort

    根据地理点距离进行排序。

    'sort' => array(
        array(
            'geo_distance_sort' => array(
                'field_name' => 'geo',
                'order' => SortOrderConst::SORT_ORDER_ASC,
                'distance_type' => GeoDistanceTypeConst::GEO_DISTANCE_PLANE,
                'points' => array('0.6,0.6')
            )
        ),
    )
  • 多类型组合排序

    先按照某列进行排序,再按照另一列进行排序。

    'sort' => array(
        array(
            'field_sort' => array(
                'field_name' => 'keyword',
                'order' => SortOrderConst::SORT_ORDER_ASC,
                'mode' => SortModeConst::SORT_MODE_AVG,
            )
        ),
        array(
            'pk_sort' => array(
                'order' => SortOrderConst::SORT_ORDER_ASC
            )
        ),
    )

翻页方式

在获取返回结果时,可以使用limit和offset或者使用token进行翻页。

  • 使用limit和offset

    当需要获取的总条数小于10000行时,可以通过limit和offset进行翻页,limit+offset<=10000。

    $request = array(
        'table_name' => 'php_sdk_test',
        'index_name' => 'php_sdk_test_search_index',
        'search_query' => array(
            'offset' => 10,
            'limit' => 10,
            'get_total_count' => true,
            'query' => array(
                'query_type' => QueryTypeConst::MATCH_ALL_QUERY
            ),
            'sort' => array(
                array(
                    'field_sort' => array(
                        'field_name' => 'keyword',
                        'order' => SortOrderConst::SORT_ORDER_ASC
                    )
                ),
            ),
            'token' => null,
        ),
        'columns_to_get' => array(
            'return_type' => ColumnReturnTypeConst::RETURN_SPECIFIED,
            'return_names' => array('col1', 'col2')
        )
    );
    $response = $otsClient->search($request);
  • 使用token进行翻页

    当符合查询条件的数据未读取完时,服务端会返回next_token,此时可以使用next_token继续读取后面的数据。

    使用token翻页后的排序方式和上一次请求的一致,无论是系统默认使用IndexSort还是自定义排序,因此设置了token不能再设置Sort。另外使用token后不能设置offset,只能依次往后读取,即无法跳页。

    $request = array(
        'table_name' => 'php_sdk_test',
        'index_name' => 'php_sdk_test_search_index',
        'search_query' => array(
            'offset' => 0,
            'limit' => 10,
            'get_total_count' => true,
            'query' => array(
                'query_type' => QueryTypeConst::FUNCTION_SCORE_QUERY,
                'query' => array(
                    'query' => array(
                        'query_type' => QueryTypeConst::TERM_QUERY,
                        'query' => array(
                            'field_name' => 'keyword',
                            'term' => 'keyword'
                        )
                    ),
                    'field_value_factor' => array(
                        'field_name' => 'long'
                    )
                )
            ),
            'sort' => array(
                array(
                    'score_sort' => array(
                        'order' => SortOrderConst::SORT_ORDER_DESC
                    )
                ),
            )
        ),
        'columns_to_get' => array(
            'return_type' => ColumnReturnTypeConst::RETURN_SPECIFIED,
            'return_names' => array('keyword', 'long')
        )
    );
    
    $response = $otsClient->search($request);
    print "total_hits: " . $response['total_hits'] . "\n";
    print json_encode($response['rows'], JSON_PRETTY_PRINT);
    
    while($response['next_token'] != null) {
        $request['search_query']['token'] = $response['next_token'];
        $request['search_query']['sort'] = null;//当有next_token时,不能再设置Sort,token中包含sort信息。
        $response = $otsClient->search($request);
        print json_encode($response['rows'], JSON_PRETTY_PRINT);
    }