Please help me change the php code from pagination from + size to search_after

please help me change the php code from pagination from + size to search_after, product_id is the unique id for sorting.

$start = ($params['page'] - 1) * $params['limit'];
$body = [
'_source' => ['product_id','name','categories','category_0_name','category_1_name','model','manufacturer'],
'query' => $query,
'from' => $start,
'size' => $params['limit'],
'sort' => ['product_id' => ['order' => asc]]
];

$search = [
    'index' => $index,
    //'type' => $type,
    'type' => '_doc',
    'body' => $body
];

$return = [
    'hits' => [],
    'total' => 0,
    'took' => null,
    'filters' => [],
];

try{
    $results = $this->client->search($search);
}catch(\Exception $e){
    $this->registry->get('log')->write('FATAL: Search failed. Error: '.$e->getMessage());
    return $return;
}

$return['took'] = $results['took'];
$return['timed_out'] = $results['timed_out'];

$language = $this->session->data['language'];

if (isset($results['hits']) && count($results['hits'])):
    $return['total'] = $results['hits']['total'];
    $return['hits'] = [];
    $position = 1;
    foreach ($results['hits']['hits'] as $hit):
        $return['hits'][] = $hit['_id'];
        $return['products'][$hit['_id']] = [
            'id' => (int) $hit['_id'],
            'product_id' =>   $hit['_source']['product_id'],
            'name' => $hit['_source']['name'][$language],
            'category_0_name' => isset($hit['_source']['category_0_name'][$language]) ? $hit['_source']['category_0_name'][$language] : '',
            'category_1_name' => isset($hit['_source']['category_1_name'][$language]) ? $hit['_source']['category_1_name'][$language] : '',
            'position' =>   $position,
            'model' =>   $hit['_source']['model'],
            'position_overall' =>   $position + $start,
            'manufacturer' => isset($hit['_source']['manufacturer']) ? $hit['_source']['manufacturer']['name'] : '_none_',
        ];
        $position++;
    endforeach;
endif;

someone in github suggested to post the question here and said this is an active forum. but the question has been posted for hours without any reply. maybe it is only a dead forum.

Please be patient in waiting for responses to your question and refrain from pinging multiple times asking for a response or opening multiple topics for the same question. This is a community forum, it may take time for someone to reply to your question. For more information please refer to the Community Code of Conduct specifically the section "Be patient". Also, please refrain from pinging folks directly, this is a forum and anyone that participates might be able to assist you.

If you are in need of a service with an SLA that covers response times for questions then you may want to consider talking to us about a subscription.

It's fine to answer on your own thread after 2 or 3 days (not including weekends) if you don't have an answer.

1 Like

I don't really know PHP but I guess you need to mimic what the REST API is expecting. Paginate search results | Elasticsearch Guide [8.13] | Elastic

Could you try and may be share the code you wrote and the problem you are facing?

Please read this about how to format.

1 Like

that website is useless, it only teaches people how to search but nothing about writing php coding.

Similar to what is shown in the search example within the documentation provided by @dadoonet, you need to include the search_after parameter in the body segment of your request instead of size. There is a note about validation on the PHP client in this issue here that, while old, is still relevant.

If that doesn't work please share the code and the behaviour/ error that you see.

2 Likes

I am nothing about PHP, below is the code, can you @carly.richmond help me change it?

public function findProducts($params) {

    $searchConfig = $this->getSearchConfigs();
    $searchFields = $this->getFieldsWeights($searchConfig['fields']);

    $index = $this->getPrimaryIndexName();
    $type = $this->indexType();

    $params['filter_include'] = isset($params['filter_include']) ? $params['filter_include'] : [];

    $this->load->library('search_plus');
    $this->client = $this->search_plus->client;

    $query = ['bool' => ['must' => []]];

    /**
     * @todo Escape query string
     */
    if ($params['search'] != ''):

        $queryString['fields'] = $searchFields;
        $queryString['analyzer'] = 'custom_analyzer';

        $words = explode(' ',$this->search_plus->escape($params['search']));
        if($searchConfig['fuzziness'] > 0):
            /**
             * Append fuzzy operator ~ to words
             */
            array_walk($words, function (&$value, $key){
                $value.='~';
            });
            $queryString['fuzziness'] = $searchConfig['fuzziness'];
        endif;

        $queryWords = implode(' ', $words);
        
        if($params['auto_complete'] > 0):

            $words = $this->search_plus->escape($params['search']).'';
            $queryString['query'] = '('.$queryWords.')^10 OR ('.$words.'*)';
        else:
            $queryString['query'] = $queryWords;
        endif;
        
        $query['bool']['must']['query_string'] = $queryString;
        $query['bool']['should']['query_string'] = $queryString;
        $query['bool']['must']['query_string']['default_operator'] = 'OR';
        $query['bool']['should']['query_string']['default_operator'] = 'AND';
        $query['bool']['should']['query_string']['boost'] = 100;

    endif;

    $filters = [];
    // status
    $filters[] = ['term' => ['status' => 1]];

    if ($params['category_id'] > 0):
        $filters[] = ['term' => ['categories' => $params['category_id']]];
    endif;

    if ($params['manufacturer_id'] > 0):
        $filters[] = ['term' => ['manufacturer.id' => $params['manufacturer_id']]];
    endif;

    if ($params['location'] != ''):
        $filters[] = ['term' => ['location.keyword' => $params['location']]];
    endif;

    $priceFilter = [];
    if ($params['price_max'] > 0):
        $priceFilter['lte'] =  $params['price_max'];
    endif;

    if ($params['price_min'] > 0):
        $priceFilter['gte'] =  $params['price_min'];
    endif;

    if(count($priceFilter)):
        $filters[]['range']['price'] =  $priceFilter;
    endif;

    if ($params['discount'] > 0):
        $filters[]['range']['discount_percent'] = ['gte' => $params['discount']];
    endif;


    $query['bool']['filter'] = $filters;
    $start = ($params['page'] - 1) * $params['limit'];
    $body = [
        '_source' => ['name','categories','category_0_name','category_1_name','model','manufacturer'],
        'query' => $query,
        'from' => $start,
        'size' => $params['limit'],
        'sort' => ['_score' => ['order' => $params['order']]]
    ];

    if($params['return_filters']):

        $body['aggregations'] = $this->getAggregationsCols($params['filter_include']);

    endif;

    $search = [
        'index' => $index,
        //'type' => $type,
        //'type' => '_doc',
        'body' => $body
    ];

    $return = [
        'hits' => [],
        'total' => 0,
        'took' => null,
        'filters' => [],
    ];

    try{
        $results = $this->client->search($search);
    }catch(\Exception $e){
        $this->registry->get('log')->write('FATAL: Search failed. Error: '.$e->getMessage());
        return $return;
    }

    $return['took'] = $results['took'];
    $return['timed_out'] = $results['timed_out'];

    $language = $this->session->data['language'];

    if (isset($results['hits']) && count($results['hits'])):
        $return['total'] = $results['hits']['total'];
        $return['hits'] = [];
        $position = 1;
        foreach ($results['hits']['hits'] as $hit):
            $return['hits'][] = $hit['_id'];
            $return['products'][$hit['_id']] = [
                'id' => (int) $hit['_id'],
                'name' => $hit['_source']['name'][$language],
                'category_0_name' => isset($hit['_source']['category_0_name'][$language]) ? $hit['_source']['category_0_name'][$language] : '',
                'category_1_name' => isset($hit['_source']['category_1_name'][$language]) ? $hit['_source']['category_1_name'][$language] : '',
                'position' =>   $position,
                'model' =>   $hit['_source']['model'],
                'position_overall' =>   $position + $start,
                'manufacturer' => isset($hit['_source']['manufacturer']) ? $hit['_source']['manufacturer']['name'] : '_none_',
            ];
            $position++;
        endforeach;
    endif;

    $return['products'] = isset($return['products']) ? array_values($return['products']) : [];

    if(isset($results['aggregations'])):

        $return['filters'] = $this->processFacets($results['aggregations']);
    endif;
    return $return;
}

Hi @chongshengdz,

Thanks for your response. Just a couple of points:

  1. We're not paid consulting here on this forum. It's best effort. We can provide examples if possible, but "please fix this code" is not how this forum works. If you have tried specific things already that would be important information to share. Also if you are stuck on something specific, or are seeing a particular error, let us know what you have tried already and what the error is and we'll do our best to help.
  2. Please ensure you strike the right tone in your messages. Adhere to the Community Code of Conduct, specifically be patient and be nice. If you continue to post inappropriate messages you will be banned.
4 Likes

ectransistors.\com/index.php?route=product/search&language=en-gb&search=Digital-to-Analog
@carly.richmond it looks like it works now, but it shows all the results on one page and each scroll page is the same (showing all results).
can you check it and see what is wrong?
'size' => 10, but it shows all results