meilisearch-php icon indicating copy to clipboard operation
meilisearch-php copied to clipboard

Expose raw settings (from Data)

Open tacman opened this issue 6 months ago • 9 comments

I'd like to see the raw settings as an array, and I can't see how to do it.

    public function getSettings(): array
    {
        return (new Settings($this->http->get(self::PATH.'/'.$this->uid.'/settings')))
            ->getIterator()->getArrayCopy();
    }

I think the easiest solution is to add a public getter to Data that gets the protected $data property.

class Data implements \ArrayAccess, \Countable, \IteratorAggregate
{
    protected $data = [];

    public function __construct(array $data = [])
    {
        $this->data = $data;
    }

    public function getData(): array
    {
        return $this->data;
    }

It could also be called getRawData()

Although it's great to have the Embedder class and everything else, sometimes I just want the raw data, especially to store with my internal database of indexes. Am I missing an easier way?

tacman avatar Jun 09 '25 12:06 tacman

We have a few occurrences of methods raw https://github.com/search?q=repo%3Ameilisearch%2Fmeilisearch-php%20raw&type=code. I usually don't like them, because they don't have an enforced type, so back in the days when meili was unstable, the user could have a breaking-change without even knowing because they used that type of method.

I see the value in your request, and I think we don't have that problem anymore, but I don't know, it seems to me that we need to find a better way to expose that type of method, wdyt @norkunas ?

brunoocasali avatar Jun 09 '25 16:06 brunoocasali

We should expose it either through an array shape or objects.. first one would be less intrusive

@tacman so getArrayCopy does not return an array?

norkunas avatar Jun 09 '25 16:06 norkunas

It is an array, but it is not the same as the raw data, which is what I want, so I can re-create the settings from a cache rather than the endpoint. (Especially since the endpoint is overly-restrictive when using a readonly key).

getArrayCopy returns an array where the keys are the class names.

tacman avatar Jun 09 '25 17:06 tacman

I don't think getRawData needs an array/object shape, though I guess if it's a type-hint that'd be helpful. Won't it depend on the server version and enabled features (e.g. experimental features)?

Of course, anyone counting on raw data to be anything but that should know it might break.

In my situation, I have over 1000 indexes and I need to manage them outside of the meilisearch server, because meilisearch is very limited in its index management. So I want to scan the indexes, store the settings in a JSONB value in my database, then I can query which indexes have used embeddings, which ones have configured specific searchable fields rather than *, etc.

But I'd rather deal with the raw data, or at least have the option to do so.

tacman avatar Jun 09 '25 17:06 tacman

If meilisearch instance can return raw data, then you can also make a direct http call to it and do what you want, unless I misunderstood something :)

norkunas avatar Jun 09 '25 17:06 norkunas

Right, but I want to use the library because it already has the authentication built in.

the getSettings() call does a bunch of things to map the settings to an object, when all I want is the array.

tacman avatar Jun 09 '25 17:06 tacman

You can't expect that a library will cover everyone's use cases ;) builtin authentication is only a auth bearer header where you inject api key,as you IIRC use symfony, you can even configure scoped client with that header,so your code does not need to manage auth injection. That's my 2cts :)

norkunas avatar Jun 09 '25 17:06 norkunas

Sure, but even philosophically, getting the raw data seems like something valuable.

I think the $http property is protected, and there's no getter for it either. So accessing the client would indeed require creating another one, which I'd like to avoid, and simply use the library.

tacman avatar Jun 09 '25 18:06 tacman

getting the raw data seems like something valuable.

That's why I'm trying to help here to get what you need faster :)

framework:
  http_client:
    scoped_clients:
      meilisearchApi.client:
        base_uri: '%env(MEILISEARCH_URL)%'
        auth_bearer: '%env(MEILISEARCH_API_KEY)%'
use Symfony\Contracts\HttpClient\HttpClientInterface;

public function __invoke(#[Autowire('@meilisearchApi.client')] private HttpClientInterface $http) {
  $raw = $http->get('indexes/$indexUid/settings')->toArray(false);
}

that's all what you need.

Looking further:

  • I've injected default http client and did this call: $this->httpClient->request('GET', 'http://meilisearch:7700/indexes/index/settings', ['auth_bearer' => '...'])->toArray(false)
  • I've injected meilisearch client and did this call: $this->client->index('...')->getSettings()

Both returned arrays with identical shape and data. ~~So from here I do not understand your needs anymore~~

Missed that some data are wrapped in sub-objects. So your point is that you need to unwrap it? You can call iterator_to_array on those sub-objects, without adding here any additional methods 🤔

norkunas avatar Jun 10 '25 04:06 norkunas