Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite query builder to support all missing methods #761

Closed
wants to merge 3 commits into from

Conversation

guestpectacular
Copy link
Contributor

@guestpectacular guestpectacular commented Sep 3, 2023

Rewrite query builder to support all missing methods

I have performed a complete internal rewrite of the where method in the Laravel/Scout package to natively support Laravel query builder methods. This allows for more flexible queries that support AND, OR, and combined multiple scopes using closures.

Current state supporting only AND operator:

// Search through users where age = 38 AND where name = 'Edgar'
User::search('Pimienta')->where('age', 38)->where('name', 'Edgar')->get();

If we need to implement a filter using OR:

User::search($this->search, function ($engine, $query, $options) {
   $options['filter'] = "age = 38 OR name = 'Edgar'";
   return $meilisearch->search($query, $options);
})->get()

What about more custom filters?

$ids	=	[1,2,3];
User::search("Pimienta", function ($engine, $query, $options) use ($ids) {
   $options['filter'] = "(age = 38 OR name = 'Edgar') OR id NOT IN [" . implode(', ', $ids) . "]";
   return $meilisearch->search($query, $options);
})->get()

The code starts to feel bloated and difficult to maintain. With this contribution, it is now possible to filter between age = 38 OR name = 'Edgar' using a cleaner syntax:

User::search('Pimienta')->where(function ($query) {
    $query->where('age', 38)->orWhere('name', 'Edgar');
})->get();

The enhanced query builder also supports custom filters, making it easier to create complex queries. For example, filtering based on age, name, and a list of excluded IDs can be accomplished as follows:

$ids = [1, 2, 3];
User::search('Pimienta')->where(function ($query) use ($ids) {
    $query->where(function ($query) {
        $query->where('age', 38)->orWhere('name', 'Edgar');
    })->orWhereNotIn('id', $ids);
})->get();

I have ported missing functions from Illuminate\Database\Query\Builder into Laravel\Scout\Builder. These include where, orWhere, whereIn, orWhereIn, whereNotIn, orWhereNotIn, whereExists, orWhereExists, whereNotExists, whereBetween, whereNull, orWhereNull, whereNotNull, whereIsEmpty, orWhereIsEmpty, whereIsNotEmpty, enabling us to practically use the same functionality as with Eloquent models.

I'm currently working on extending this functionality to support Algolia. Until this transition is complete, I've added a helper method enableMeilisearchNewQueryBuilder that allows users to enable the new query builder features:

Model::enableMeilisearchNewQueryBuilder()->whereIn('id', 3);

Benefits:

  • This enhancement significantly improves the query building capabilities of Laravel Scout, making it more powerful and user-friendly.
  • Developers can now create more complex and expressive search queries using a familiar Laravel syntax.
  • The contribution makes it easier to work with Elasticsearch and seamlessly integrates with Laravel's query builder.

I'm actively working on extending this functionality to support Algolia, which will complete the transition to using this new query builder across different search engines. Further discussions and collaboration on this are welcome.

Please review and provide feedback on this pull request. Your input is greatly appreciated.

Thank you for your time and consideration.

@driesvints
Copy link
Member

Thanks. Can you please:

  • Undo all unrelated styling changes
  • Fix the tests

Then afterwards mark as ready for review.

@driesvints driesvints marked this pull request as draft September 4, 2023 08:46
Add all missing methods from Illuminate\Database\Query\Builder into Laravel\Scout\Builder, where, orWhere, whereIn, orWhereIn, whereNotIn, orWhereNotIn, whereExists, orWhereExists, whereNotExists, whereBetween, whereNull, orWhereNull, whereNotNull, whereIsEmpty, orWhereIsEmpty, whereIsNotEmpty.
Add tests.
Add all missing methods from Illuminate\Database\Query\Builder into Laravel\Scout\Builder, where, orWhere, whereIn, orWhereIn, whereNotIn, orWhereNotIn, whereExists, orWhereExists, whereNotExists, whereBetween, whereNull, orWhereNull, whereNotNull, whereIsEmpty, orWhereIsEmpty, whereIsNotEmpty.
Add tests.
# Conflicts:
#	src/Builder.php
#	src/Engines/MeilisearchEngine.php
#	tests/Unit/MeilisearchEngineTest.php
@guestpectacular guestpectacular marked this pull request as ready for review September 4, 2023 19:21
@guestpectacular
Copy link
Contributor Author

guestpectacular commented Sep 4, 2023

Hi @driesvints, I need guidance on how to detect the current search engine used at runtime directly from the package, rather than relying on Laravel to enable a smoother transition between versions once the Algolia engine it's finished, any help or pointers would be greatly appreciated!

@taylorotwell
Copy link
Member

The point of Scout is not to provide a 1-to-1 match with the query builder - it is simply to provide a common set of search primitives. This will become a leaky abstraction.

@guestpectacular
Copy link
Contributor Author

Roger that.

Do you have any tip to help me detect the current search engine used at runtime directly from the package itself?

yhbyun added a commit to yhbyun/scout that referenced this pull request Oct 9, 2024
검색 필터에서 or 그리고 nested 쿼리가 필요했으나 scout가 지원을 하지
않아서 수정함.
laravel#761
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants