Open alexander-schranz opened 1 year ago
The problems I see here:
serialize()
, don't you think? So maybe this is something we should address first. manager
š Is that how you name it in SEAL? Or is it what other engines use?However, I think it would be a great addition. It could also be the place where you could copy and merge two indexes or other stuff. So I'm not necessarily against having it in Loupe itself.
I think we should make the configuration serializable as JSON rather than using serialize(), don't you think? So maybe this is something we should address first.
I have currently a similar issue on SEAL where its still on my list to discuss once with nicolas from symfony what the best way is to cache such files which don't change between deployments and make usage of the opcache maybe.
I don't like the word manager š Is that how you name it in SEAL? Or is it what other engines use?
I don't have a word yet in SEAL currently I just named it Helper because I did not come up with a better name. Then I was thinking about entityManager from doctrine and so got to the LoupeManager name. In the other engines it is always the Client
instance which they provide but would in case of Loupe be not a good name I think.
Okay, I see. Well, I'm totally open to having this in Loupe itself - I think it could be valuable not just for SEAL š
Another naming idea could be:
LoupeManager
/ LoupeHelper
-> Loupe
Loupe
-> Index
LoupeFactory
-> IndexFactory
If anyone's looking for a very much reduced version of an index manager that creates, drops, and initialises multiple indexes, this is what I'm currently using in Laravel/Statamic land.
<?php
use Illuminate\Support\Facades\File;
use Loupe\Loupe\Configuration;
use Loupe\Loupe\Loupe;
use Loupe\Loupe\LoupeFactory;
use Statamic\Facades\Path;
class Manager
{
/**
* @var Loupe[]
*/
protected array $clients = [];
public function __construct(
protected readonly LoupeFactory $factory,
protected string $path,
) {
if (! File::isDirectory($this->path)) {
File::makeDirectory($this->path, recursive: true);
}
}
public function get(string $index, Configuration $configuration): Loupe
{
return ($this->clients[$index] ??= $this->make($index, $configuration));
}
public function make(string $index, Configuration $configuration): Loupe
{
$this->createIndex($index);
return $this->factory->create($this->indexDirectory($index), $configuration);
}
public function indexDirectory(string $index): string
{
return Path::resolve("{$this->path}/{$index}");
}
public function indexPath(string $index): string
{
return Path::resolve("{$this->path}/{$index}/loupe.db");
}
public function indexExists(string $index): bool
{
return File::exists($this->indexPath($index));
}
public function createIndex(string $index): void
{
if (! File::isDirectory($dir = $this->indexDirectory($index))) {
File::makeDirectory($dir, recursive: true);
}
if (! File::exists($db = $this->indexPath($index))) {
File::put($db, '');
}
}
public function dropIndex(string $index): void
{
File::deleteDirectory($this->indexDirectory($index));
}
}
Nice! Guys, feel free to PR your solutions - I think it would be nice having such a manager. The only requirement from my side: No new dependencies for file handling if possible - if not, then symfony/filesystem
because I'm already using this for require-dev
.
I think Laravel uses Symfony Filesystem under the hood, but let me double check.
Is this issue fixed with https://github.com/loupe-php/loupe/pull/108?
@zonky2 No, we closed that PR as it didn't prove to be very thought through :) There's an upcoming feature for deleting all documents, i.e. clearing the index, that might serve your purpose.
What is a little bit different to other search engines is that at creating the Loupe instance (what in other cases is the client) the whole configuration searchablefields, filterablefields, .. is required where in other cases this I only need to know about in the SchemeManager where I call createIndex method not in cases of searching or indexing documents.
For this I created this Helper class which could also be called LoupeManager. It even serialize the configuration into a file this way it is more strict as changing updating the configuration can only be done like in other engine via the SchemaManager::createIndex method and so it is more consistent through the whole library and so without calling that the changes apply no effects.
For my usecases I maybe will be changing it when I got more time.
But it could also be part of Loupe, a none SEAL related LoupeManager could look like this. What do you think about it?
This could be achieved by a LoupeManager which looks like this:
Save the configuration can let the search engine run with the data it was created it and make the changing the configuration a more active method call can even allow to have 2 instances of a Index a Read with old configuration and a Write with the new configuration.
Maybe the configuration could be saved in the database also so only one file exists and easier to support in memory with the same case.
Overall I understand also that this could be make things to complicated and I'm fine to keep the LoupeHelper / LoupeManager in SEAL.