Setup meilsearch (part 1)

This commit is contained in:
Zoe Roux 2023-10-28 18:23:50 +02:00
parent 12f35fefc4
commit 4368f0cbe5
7 changed files with 179 additions and 38 deletions

View File

@ -34,7 +34,7 @@ POSTGRES_DB=kyooDB
POSTGRES_SERVER=postgres
POSTGRES_PORT=5432
MEILI_HTTP_ADDR="http://meilisearch:7700"
MEILI_HOST="http://meilisearch:7700"
MEILI_MASTER_KEY="ghvjkgisbgkbgskegblfqbgjkebbhgwkjfb"
# vi: ft=sh

View File

@ -15,6 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{FEAE1B0E
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Host", "src\Kyoo.Host\Kyoo.Host.csproj", "{0938459E-2E2B-457F-8120-7D8CA93866A6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Meilisearch", "src\Kyoo.Meilisearch\Kyoo.Meilisearch.csproj", "{F8E6018A-FD51-40EB-99FF-A26BA59F2762}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -61,6 +63,10 @@ Global
{0938459E-2E2B-457F-8120-7D8CA93866A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0938459E-2E2B-457F-8120-7D8CA93866A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0938459E-2E2B-457F-8120-7D8CA93866A6}.Release|Any CPU.Build.0 = Release|Any CPU
{F8E6018A-FD51-40EB-99FF-A26BA59F2762}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8E6018A-FD51-40EB-99FF-A26BA59F2762}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8E6018A-FD51-40EB-99FF-A26BA59F2762}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8E6018A-FD51-40EB-99FF-A26BA59F2762}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0C8AA7EA-E723-4532-852F-35AA4E8AFED5} = {FEAE1B0E-D797-470F-9030-0EF743575ECC}

View File

@ -23,46 +23,12 @@ namespace Kyoo.Abstractions.Models
/// <summary>
/// Results of a search request.
/// </summary>
public class SearchResult
public class SearchPage<T> : Page<T>
where T : class, IResource
{
/// <summary>
/// The query of the search request.
/// </summary>
public string Query { get; init; }
/// <summary>
/// The collections that matched the search.
/// </summary>
public ICollection<Collection> Collections { get; init; }
/// <summary>
/// The items that matched the search.
/// </summary>
public ICollection<LibraryItem> Items { get; init; }
/// <summary>
/// The movies that matched the search.
/// </summary>
public ICollection<Movie> Movies { get; init; }
/// <summary>
/// The shows that matched the search.
/// </summary>
public ICollection<Show> Shows { get; init; }
/// <summary>
/// The episodes that matched the search.
/// </summary>
public ICollection<Episode> Episodes { get; init; }
/// <summary>
/// The people that matched the search.
/// </summary>
public ICollection<People> People { get; init; }
/// <summary>
/// The studios that matched the search.
/// </summary>
public ICollection<Studio> Studios { get; init; }
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Kyoo.Meilisearch</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MeiliSearch" Version="0.14.6" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../Kyoo.Abstractions/Kyoo.Abstractions.csproj" />
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,95 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using Autofac;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Meilisearch;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.Meiliseach
{
public class MeilisearchModule : IPlugin
{
/// <inheritdoc />
public string Name => "Meilisearch";
private readonly IConfiguration _configuration;
public MeilisearchModule(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// Init meilisearch indexes.
/// </summary>
/// <param name="provider">The service list to retrieve the meilisearch client</param>
public static async Task Initialize(IServiceProvider provider)
{
MeilisearchClient client = provider.GetRequiredService<MeilisearchClient>();
await _CreateIndex(client, "items", new Settings()
{
SearchableAttributes = new[]
{
nameof(LibraryItem.Name),
nameof(LibraryItem.Slug),
nameof(LibraryItem.Aliases),
nameof(LibraryItem.Path),
nameof(LibraryItem.Tags),
// Overview could be included as well but I think it would be better without.
},
FilterableAttributes = new[]
{
nameof(LibraryItem.Genres),
nameof(LibraryItem.Status),
nameof(LibraryItem.AirDate),
nameof(LibraryItem.StudioID),
},
SortableAttributes = new[]
{
nameof(LibraryItem.AirDate),
nameof(LibraryItem.AddedDate),
nameof(LibraryItem.Kind),
},
DisplayedAttributes = new[] { nameof(LibraryItem.Id) },
// TODO: Add stopwords
// TODO: Extend default ranking to add ratings.
});
}
private static async Task _CreateIndex(MeilisearchClient client, string index, Settings opts)
{
TaskInfo task = await client.CreateIndexAsync(index, "Id");
await client.WaitForTaskAsync(task.TaskUid);
await client.Index(index).UpdateSettingsAsync(opts);
}
/// <inheritdoc />
public void Configure(ContainerBuilder builder)
{
builder.RegisterInstance(new MeilisearchClient(
_configuration.GetValue("MEILI_HOST", "http://meilisearch:7700"),
_configuration.GetValue<string?>("MEILI_MASTER_KEY")
)).InstancePerLifetimeScope();
builder.RegisterType<SearchManager>().InstancePerLifetimeScope();
}
}
}

View File

@ -0,0 +1,58 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Utils;
using Meilisearch;
namespace Kyoo.Meiliseach;
public class SearchManager
{
private readonly MeilisearchClient _client;
private readonly ILibraryManager _libraryManager;
public SearchManager(MeilisearchClient client, ILibraryManager libraryManager)
{
_client = client;
_libraryManager = libraryManager;
_libraryManager.Movies.OnCreated += (x) => _CreateOrUpdate("items", x);
_libraryManager.Movies.OnEdited += (x) => _CreateOrUpdate("items", x);
_libraryManager.Movies.OnDeleted += (x) => _Delete("items", x.Id);
}
private Task _CreateOrUpdate(string index, IResource item)
{
return _client.Index(index).AddDocumentsAsync(new[] { item });
}
private Task _Delete(string index, int id)
{
return _client.Index(index).DeleteOneDocumentAsync(id);
}
private async Task<ICollection<T>> _Search<T>(string index, string? query, Include<T>? include = default)
{
ISearchable<IResource> res = await _client.Index(index).SearchAsync<IResource>(query, new SearchQuery()
{
});
throw new NotImplementedException();
}
}

View File

@ -22,6 +22,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\" />
<Folder Include="Migrations\" />
</ItemGroup>
</Project>