Giter Site home page Giter Site logo

Comments (8)

Tucker-Eric avatar Tucker-Eric commented on June 10, 2024

Yep! That same approach would still work!

from eloquentfilter.

francoism90 avatar francoism90 commented on June 10, 2024

@Tucker-Eric Thanks! That indeed seems to work.

However I'm thinking of this approach with Meilisearch:

public function handle()
    {
        parent::handle();

        $filters = $this->query->get()->map(function($model) {
            return 'id = '.$model->id;
        })->join(' OR ');

        // Overwrite QueryBuilder with ScoutBuilder
        $this->query = $this->getModel()->search(
            $this->input('query', ''),
            function ($engine, string $query, array $options) use ($filters) {
                $options['filters'] = $filters;

                return $engine->search($query, $options);
            }
        );

        return $this->query;
    }

This would mean I can use the filters and return a Laravel Scout (pagina) instance afterwards.

Any downsides of using this approach?

Thanks!

from eloquentfilter.

Tucker-Eric avatar Tucker-Eric commented on June 10, 2024

That looks like it works. I don't see any downsides. Maybe some minor optimizations and use a whereIn instead of joining the results on OR

from eloquentfilter.

francoism90 avatar francoism90 commented on June 10, 2024

@Tucker-Eric Unfortunately it doesn't seem work with a large dataset.

The query simple selects all results (e.g. select * from books in handle) each time doing a request. The final query uses take/skip, which actually is correct because of adding the paginate method in the controller.

The only workaround I think would be to integrate the paginate method in handle (ModelFilter class) instead of adding it afterwards?

Ps. I need to use the direct filter with OR unfortunately, this is a limitation of the engine as it doesn't provide any whereIn.

from eloquentfilter.

Tucker-Eric avatar Tucker-Eric commented on June 10, 2024

Are you referring to something like this?

public function handle()
{
    $filters = parent::handle()
        ->paginateFilter()
        ->getCollection()
        ->pluck('id')
        ->join(' OR ')

    // Overwrite QueryBuilder with ScoutBuilder
    return $this->query = $this->getModel()->search(
        $this->input('query', ''),
        function ($engine, string $query, array $options) use ($filters) {
            $options['filters'] = $filters;

            return $engine->search($query, $options);
        }
    );
}

from eloquentfilter.

francoism90 avatar francoism90 commented on June 10, 2024

@Tucker-Eric Thanks for helping me., really appreciate it :)

$filters = parent::handle()
            ->paginateFilter()
            ->getCollection()
            ->pluck('id')
            ->map(fn($id) => 'id = '.$id)
            ->join(' OR ');

        // Overwrite QueryBuilder with ScoutBuilder
        return $this->query = $this->getModel()->search(
            $this->input('query', ''),
            function ($engine, string $query, array $options) use ($filters) {
                $options['filters'] = $filters;

                return $engine->search($query, $options);
            }
        );

This works fine. :)

The first page is loaded correctly, trying to load the second page seems to reset the paginate collection.

This is my IndexController.php:

class IndexController extends Controller
{
    public function __invoke(Request $request): ResourceCollection
    {
        $books = Book::filter($request->all(), BookFilter::class)->simplePaginate();

        return BookResource::collection($books);
    }
}

Should I call something different here?

from eloquentfilter.

Tucker-Eric avatar Tucker-Eric commented on June 10, 2024

I would almost suggest using scout search to get the id's instead of the filter and then filter and paginate in the filter. You could even throw that into a query method that will automatically get resolved when that input parameter is present.

public function query($query)
{
    $ids = $this->getModel()
        ->search($query)
        ->get()
        ->pluck('id');

    return $this->whereIn('id', $ids);
}

Then your controller can work the same or you can use the simplePaginateFilter in the controller:

class IndexController extends Controller
{
    public function __invoke(Request $request): ResourceCollection
    {
        $books = Book::filter($request->all(), BookFilter::class)->simplePaginateFilter();

        return BookResource::collection($books);
    }
}

from eloquentfilter.

francoism90 avatar francoism90 commented on June 10, 2024

@Tucker-Eric This seems indeed the best solution. Maybe Laravel Scout is too limited and should add some features to make it easier to integrate with the QueryBuilder.

Thanks for the help and your time. :)

from eloquentfilter.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.