babenkoivan / elastic-scout-driver-plus

Extension for Elastic Scout Driver
MIT License
267 stars 52 forks source link

Filter Returns Empty Result #106

Closed zahidhasanemon closed 2 years ago

zahidhasanemon commented 2 years ago

I am using following versions | PHP | 7.4 | Elasticsearch | 7.16 | Laravel | 6 | Laravel Scout | 8.6 | elastic-scout-driver | 2.0 | elastic-scout-driver-plus | 3.1

I want to search and filter data at the same time. Search from a field and filter from another field. Search string must match in that search field and filter field should contain one of the values from an array. So I am making query like

$must = Query::match()
     ->field('full_text_search') // string field to search from
     ->query($normalizedSearchString); // $normalizedSearchString is the search string

$filter = Query::terms()
    ->field('authorList') // authorList is a field of single or multiple author name string (separated with (, ) comma and a space if multiple)
    ->values($authorFilter);  // $authorFilter is an array with single or multiple values (full name of author)

$query = Query::bool()->must($must)->filter($filter);
$finalSearchResult = Product::searchQuery($query)->size(10000)->execute();
$books = $finalSearchResult->models();

This returns no result. But if I omit the filter, only search query is returning expected result.

$query = Query::bool()->must($must);
$finalSearchResult = Product::searchQuery($query)->size(10000)->execute();

Is my approach wrong? What should be the right way to query to get my expected result?

babenkoivan commented 2 years ago

Hi @zahidhasanemon,

The term search finds documents based on the exact value match. Therefore, it's better to define authorList as a keyword type in your mapping. In addition, authorList should be indexed as an array of values and not a single string, i.e.:

public function toSearchableArray()
{
   return [
       // other fields
      'authorList' => explode(',', $this->authorList) // you probably also need to trim each value
   ];
}

I hope this will give you the right direction. I'm closing this issue, cause it's a more ES-related question and not a package bug or a feature request.

zahidhasanemon commented 2 years ago

@babenkoivan thank you very much for your suggestion and I am able to solve the filter. I need one more help if you may please. I am trying to sort by created_at field. I have added the field in toSearchableArray method.

public function toSearchableArray()
{
    return [
        'full_text_search' => $this->full_text_search,
        'min_price' => $this->min_price,
        'created_at' => $this->created_at->timestamp,
        'authorList' => $this->authors,
    ];
}

and trying to sort like $listBooks = Product::searchQuery($query)->sort('created_at', 'asc')->paginate(40)->onlyModels(); but I am getting Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. and I checked in kibana created_at field is indexed as string. I am able to sort by number fields like min_price. How can I sort using created_at filed??

babenkoivan commented 2 years ago

Hey @zahidhasanemon, you need to make sure that your index has a proper mapping. created_at must be of date type with the corresponding format. You can use this package to create indices, update mapping, etc.