-
Notifications
You must be signed in to change notification settings - Fork 99
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
Improve the search() method #119
Comments
Hello @Guikingone! Let's come back to your idea, tell me if I'm wrong, there would be two ways to use it: search_result_object = $index->search('prince', options)
search_result_object->filters(your_callable)
print_r(serach_result_object->getHits) or directly:
I like this In the same idea, we (the Meili team) also noticed a need from the users: the need to sort/apply modification on the search_result_object = $index->search('prince', null, null, my_callable_for_facets_distribution) ? I know the If you are around, what do you think @shokme and @ppshobi? Does the @Guikingone suggestion bring a great developer experience from your POV? 🙂 |
Hello @curquiza 👋 Yes, sorry for the lack of details, here's the use case (maybe an edge case? 😄 ) that I'm facing:
I could specify facetFilters but what If I want to filter the hits this way:
This will not trigger a second search as I only need to filter the hits retrieved via MS, plus, I can use a specific filter/mutation on the hits as you mentioned (IMO, this could be a new document load but that's an other point). On the usages, yes, both syntaxes are valid, IMO, the The The use case that you're talking about could also be integrated IMO, it does not make the method "heavy" IMO as it's an optional argument. If the "configuration" aspect of the method is important, maybe an array of "options" can be introduced: public function search($query, array $options = [], array $extraConfiguration = []): array
{
$parameters = array_merge(
['q' => $query],
$options
);
$result = $this->http->post(self::PATH.'/'.$this->uid.'/search', $parameters);
if (array_key_exist('hitsFilter', $extraConfiguration) {
$result['hits'] = array_filter($result['hits'], $extraConfiguration['hitsFilter'], ARRAY_FILTER_USE_BOTH);
}
return $result;
} Same idea can be applied to |
Thanks for the details about your usecases, I understand better! 👍 I like your idea about Here what I suggest for the associated PR:
search($query, array $search_params = [], array $options = []) The
|
Also, about the The real I'm aware this is a bad naming coming from MeiliSearch, the name
Be sure I'm going to discuss this with the team. TLDR; do not use And sorry about this digression, but I wanted to be sure everyone is aware of this since I think this is not obvious from my POV. |
IMO, the Thanks for the informations about The PR should be up later this day and mention this issue 🙂 |
Even though I like the idea of having a DTO class for our search results, I would like to point out some cons here. I'm not sure why something like this can be the burden of the user who wants to wrap the results in one of the classes that they like? Rather than we introduce a class from our side? I ask this because just like @Guikingone said and I quote
I personally don't like mutating the data via some callbacks/static methods (Due to the fact that unexpected side effects can happen through these kinds of opportunities,) But if you want it for some reasonm it can be done from the user land, rather than we enforce it. without any performance issues or confusions. Also having a class like this being the default return types can create breaking changes quite often, rather than we return a plain array, since every client depends on it understand it without any additional modification( eg: laravel-scout) Having a plain array return type will always make sure that we remain cross compatible with meilisearch-core (well, mostly) and the clients depend on us without any additional effort. Otherwise we will have to keep adding methods into this giant class for every field or functionality meilisearch-core introduces. So why not keep the use of these type of classes in the user land itself? |
@ppshobi Actually, it depends regarding the return typehint, the first idea was to remove the
Actually, When it comes to the clients, I don't know if When it comes to adding methods and improving the class over time, keep in mind that every other classes requires to be updated according to new MS features, that's a normal thing IMHO, I agree that this issue is not about a new feature. Again, that's just an idea/suggestion, if it doesn't fit, you can easily close the PR/issue and keep the current API as it 🙂 |
I think the whole thing should be on the userland, rather than we package it ourselves. let the user create abstractions if required. |
Hello @ppshobi, thanks for your feedback 😄 I personally would rather manipulate an instance of a class instead of a raw array. That's why I like using an SDK instead of a really basic API wrapper: having classes and methods provided by the library to make the experience easier. That's why I find the idea of @Guikingone is a good idea because it improves the dev experience IMO. About the maintenance issue, I understand this class brings more maintenance, but I'm not afraid about this because we indeed work closely with the core team of MeiliSearch: make all the SDKs up-to-date with the last version of MeiliSearch is always a priority for us. So the changes in the About the potential increase of breaking changes that could impact the libraries depending on meilisearch-php (laravel-scout and symfony plugins): I'm not really sure to understand how this could happen more often.
But maybe I miss something. |
For example
This SDK doesn't need any changes at all (not that the work is heavy to modify the codebase), only the user-land libraries or code needs to be updated. They will know this this issue even without reading the exact sdk documentation, rather meilisearch documentation/upgrade guide would suffice. So, WE are not breaking anything. Plain arrays are so flexible it does whatever we need, for example we don't need to do any additional work on serialization, deserialization, encoding/decoding etc... Also, this will ensure that multiple meilisearch version work among many versions of SDK. Another example is when meilisearch introduces a new field, then also we don't need to do any work, by default it exposes all the fields as simple as possible (i.e: No need to call This class abstracts the array and add getters on top of it. Which you can do from the array itself, just that the syntax is different and less work and simple. Call me lazy 😂 , But why take airplane to goto another room where you can simply go there. Plus the algolia and elasticsearch api clients return plain arrays. |
I'm not okay with this statement as for now, previous versions have introduced BC breaks (think about the introduction of BUT, obviously, when this SDK is tagged
Flexible, yes, performant, that's a point that need to be debated IMO 😄 When it comes to introducing a new field, for now, it only needs a getter/attribute, IMHO, that's not a lof of work and BTW, every SDK needs to be updated if a new field is introduced. That's just my vision here, nothing personal against your message 🙂 |
Yes, the examples you mentioned are what I mean about maintenance I'm not really afraid of. This will be the job of the Meili Integration team to update it! Yes Algolia and Elastic return arrays, but they have a lot of other high-level tools (using those API wrappers) we don't have yet. So fewer people use the client directly I guess. We already have symfony and laravel plugins but that's just the beginning. That why I would take the opportunity a contributor as @Guikingone provides this kind of feature, improving the dev experience of our current libraries. |
I can agree here that BC breaks are bound to happen, but my question is why do it unnecessarily when a simple solution covers that for free
So, you mean a class over an array is more performant?
I didn't get this part, but Imagine you need to send the search result to another backend; how would you do it for example you want to encode it in url? |
Depending on the use case, yes, here's a link (not the one that I wanted to share but the first that I retrieved in my bookmarks 😄 ).
It depends, let's imagine that you need to send it to a REST API, you can just: json_endode($result->getHits()); Same applies for URL's, it depends on the required format, BTW, encoding the result of a search into the URL is strange IMHO 🤔 If the idea is to send it to another backend, it depends on the format required but actually, the |
From the link you shared seems like the article got translated from some other language using google translate. I was not able to understand a thing. Something was missing and no citations for any arguments. Regardless we are not replacing the array rather this class is on top of the array, anyway array access happens all the time. So, the performance argument is not valid here. Regarding the second part, I was saying
all of the above would work if the class is not there. instead of This is my personal opinion, Because I have struggled with unnecessary abstractions in codebase. If everyone else is happy, let's go with it. |
IMO, the performances argument still relevant, the link that I've shared don't, here's the ressources I've been looking for:
I agree on the simplicity, problem is, when it comes to interacting with the "results" array, using an object is a better idea and a better DX without a lot of extra layers, again, I could be wrong 🙂 |
I think it comes down to the problems similar to the single vs double quote debates. In reality we rarely bother about them. From the links that you have given, the associative arrays were was assessed by sorting a really large array where the classed version was performing well with a barely noticeable change in performance with less memory. But at the same time serialization performance were really subpar. The pros and cons are anyways there. In our case we are just accessing elements of one array, so maybe it would have been better, If you were showing the access time for class vs array. Regardless we can argue more about why such a thing in real scenario would be happening and when optimizing such thing is needed. A real performance optimization can be where, when we open multiple DB connections and try to reuse some of those connections, which can have significant performance gains. Which is far productive than of debating about whether we should keep the connection string in double or single quotes. |
Hello @Guikingone and @ppshobi! I discussed with the laravel and symfony plugin maintainers: there are ok with this change since the Meili team is comfortable with announcing breaking changes -> Yes, we are, we are trying to create the best tools in terms of dev experiences. And this, unfortunately, involves breaking changes, which is ok since we are in an early stage. About performance issues the users may encounter in some context: we could also (this would need a new issue and a new PR) add an option to the |
Hello @curquiza, sorry for the delay I agree on the new option, IMHO, we could implement this behaviour in the current PR without taking too much time and BC breaks, the idea is to have 2 type of return if I'm right?
|
Hello @Guikingone! No worries for the delay: thank you for still being involved in this issue 👍 Yes, if the search method is called with the search('prince', null, [ 'getRawSearch': true ]); By default, the search method returns a Another addition I would like to see: a If you don't have time to do one or both changes, tell me, I will do them after merging your PR 🙂 |
(I don't know your opinion about this: but I can't wait for threads in GitHub issues!) |
❤️ 😄 No problem on my side to handle the modifications, I'll take a look at it tonight 🙂 |
Small update, I've pushed a first POC of the |
120: Indexes::search() improvements r=curquiza a=Guikingone Hi everyone 👋 As mentioned here: #119, here's the `SearchResult` class and the improvements that comes with it. There's just a small "DX" way that I'm not sure about: - When using `SearchResult::filter()` should the `hits` array be reset to 0 or stay as it? IMO, the array could stays as it as we return a new `SearchResult` object but sometimes, it could be good idea to reset the keys from 0 (loops, etc) 🤔 Thanks for the feedback and have a great day 🙂 Co-authored-by: Loulier Guillaume <[email protected]>
80: Fix getTotalCount() method r=curquiza a=curquiza Remove `nbHits` usage because this is not reliable information. The Meili team is aware of this. Here are the different issues and comments about it to explain why it's confusing, and why we should not use it: - meilisearch/meilisearch#1120 - meilisearch/documentation#561 - meilisearch/meilisearch-php#119 (comment) TLDR; `nbHits` is not reliable for pagination because can be exhaustive or not, depending on the value of `exhaustiveNbHits` that MeiliSearch returns which is always `false` for the moment. We are sorry for this. We all hope this confusion will be fixed asap in MeiliSearch.⚠️ The linter error in the CI will be fixed with #82 Co-authored-by: Clémentine Urquizar <[email protected]>
Hi everyone 👋
Small issue here (more a feature idea in fact), after using the
search()
method recently, I've faced a use case where aSearchResult
object could be a good idea: sorting hits.Actually, we can easily sort hits via native functions but it force use to grab the
hits
key, sort and put back it on the result array, it works but thinking on terms of DX, that's probably not an "easy" way of doing it.So, the idea is to add a new class and update the
search
method:Here's the
SearchResult
that I'm thinking about:The interesting method here is:
This one allows to filter the hits and return a filtered result without triggering a new search (a method
retry()
could trigger a new search if needed).Of course, this class is not required as the developer can always retrieve an array but it could act as an helper when advanced use cases occurs and we need to mutate the result before playing with it.
Let me know if this improvements is a good idea and if it fits the current lib API, thanks for the feedback and have a great day 🙂
PS: Maybe the current API can be mutated to add a third argument in
search
(typedcallable
) that allows us to filter the result before retrieving it and without using an object if a new class is not an option.The text was updated successfully, but these errors were encountered: