[backend] Also search in alt text
This commit is contained in:
parent
83ab277a7e
commit
8998cd2874
6 changed files with 88 additions and 16 deletions
|
@ -636,6 +636,9 @@ public class DatabaseContext(DbContextOptions<DatabaseContext> options)
|
||||||
entity.HasIndex(e => e.Cw, "GIN_TRGM_note_cw")
|
entity.HasIndex(e => e.Cw, "GIN_TRGM_note_cw")
|
||||||
.HasMethod("gin")
|
.HasMethod("gin")
|
||||||
.HasOperators("gin_trgm_ops");
|
.HasOperators("gin_trgm_ops");
|
||||||
|
entity.HasIndex(e => e.CombinedAltText, "GIN_TRGM_note_combined_alt_text")
|
||||||
|
.HasMethod("gin")
|
||||||
|
.HasOperators("gin_trgm_ops");
|
||||||
|
|
||||||
entity.Property(e => e.AttachedFileTypes).HasDefaultValueSql("'{}'::character varying[]");
|
entity.Property(e => e.AttachedFileTypes).HasDefaultValueSql("'{}'::character varying[]");
|
||||||
entity.Property(e => e.ChannelId).HasComment("The ID of source channel.");
|
entity.Property(e => e.ChannelId).HasComment("The ID of source channel.");
|
||||||
|
|
|
@ -2350,6 +2350,10 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
|
||||||
.HasColumnName("channelId")
|
.HasColumnName("channelId")
|
||||||
.HasComment("The ID of source channel.");
|
.HasComment("The ID of source channel.");
|
||||||
|
|
||||||
|
b.Property<string>("CombinedAltText")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("combinedAltText");
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.HasColumnType("timestamp with time zone")
|
.HasColumnType("timestamp with time zone")
|
||||||
.HasColumnName("createdAt")
|
.HasColumnName("createdAt")
|
||||||
|
@ -2597,6 +2601,11 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
|
||||||
|
|
||||||
b.HasIndex("UserId", "Id");
|
b.HasIndex("UserId", "Id");
|
||||||
|
|
||||||
|
b.HasIndex(new[] { "CombinedAltText" }, "GIN_TRGM_note_combined_alt_text");
|
||||||
|
|
||||||
|
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex(new[] { "CombinedAltText" }, "GIN_TRGM_note_combined_alt_text"), "gin");
|
||||||
|
NpgsqlIndexBuilderExtensions.HasOperators(b.HasIndex(new[] { "CombinedAltText" }, "GIN_TRGM_note_combined_alt_text"), new[] { "gin_trgm_ops" });
|
||||||
|
|
||||||
b.HasIndex(new[] { "Cw" }, "GIN_TRGM_note_cw");
|
b.HasIndex(new[] { "Cw" }, "GIN_TRGM_note_cw");
|
||||||
|
|
||||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex(new[] { "Cw" }, "GIN_TRGM_note_cw"), "gin");
|
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex(new[] { "Cw" }, "GIN_TRGM_note_cw"), "gin");
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Iceshrimp.Backend.Core.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
[DbContext(typeof(DatabaseContext))]
|
||||||
|
[Migration("20240527231353_AddNoteCombinedAltTextField")]
|
||||||
|
public partial class AddNoteCombinedAltTextField : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "combinedAltText",
|
||||||
|
table: "note",
|
||||||
|
type: "text",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
Console.WriteLine("Indexing drive file alt text, please hang tight!");
|
||||||
|
Console.WriteLine("This may take a long time (15-30 minutes), especially if your database is unusually large or you're running low end hardware.");
|
||||||
|
migrationBuilder.Sql("""UPDATE note SET "combinedAltText"=(SELECT string_agg(comment, ' ') FROM drive_file WHERE id = ANY ("fileIds")) WHERE "fileIds" != '{}';""");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "GIN_TRGM_note_combined_alt_text",
|
||||||
|
table: "note",
|
||||||
|
column: "combinedAltText")
|
||||||
|
.Annotation("Npgsql:IndexMethod", "gin")
|
||||||
|
.Annotation("Npgsql:IndexOperators", new[] { "gin_trgm_ops" });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "GIN_TRGM_note_combined_alt_text",
|
||||||
|
table: "note");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "combinedAltText",
|
||||||
|
table: "note");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -219,6 +219,9 @@ public class Note : IEntity
|
||||||
[Column("repliesFetchedAt")]
|
[Column("repliesFetchedAt")]
|
||||||
public DateTime? RepliesFetchedAt { get;set; }
|
public DateTime? RepliesFetchedAt { get;set; }
|
||||||
|
|
||||||
|
[Column("combinedAltText")]
|
||||||
|
public string? CombinedAltText { get; set; }
|
||||||
|
|
||||||
[ForeignKey(nameof(ChannelId))]
|
[ForeignKey(nameof(ChannelId))]
|
||||||
[InverseProperty(nameof(Tables.Channel.Notes))]
|
[InverseProperty(nameof(Tables.Channel.Notes))]
|
||||||
public virtual Channel? Channel { get; set; }
|
public virtual Channel? Channel { get; set; }
|
||||||
|
|
|
@ -37,8 +37,7 @@ public static class QueryableFtsExtensions
|
||||||
MiscFilter miscFilter => current.ApplyMiscFilter(miscFilter, user),
|
MiscFilter miscFilter => current.ApplyMiscFilter(miscFilter, user),
|
||||||
ReplyFilter replyFilter => current.ApplyReplyFilter(replyFilter, config, db),
|
ReplyFilter replyFilter => current.ApplyReplyFilter(replyFilter, config, db),
|
||||||
WordFilter wordFilter => current.ApplyWordFilter(wordFilter, caseSensitivity, matchType),
|
WordFilter wordFilter => current.ApplyWordFilter(wordFilter, caseSensitivity, matchType),
|
||||||
MultiWordFilter multiWordFilter =>
|
MultiWordFilter multiWordFilter => current.ApplyMultiWordFilter(multiWordFilter, caseSensitivity, matchType),
|
||||||
current.ApplyMultiWordFilter(multiWordFilter, caseSensitivity, matchType),
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(filter))
|
_ => throw new ArgumentOutOfRangeException(nameof(filter))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -264,31 +263,37 @@ public static class QueryableFtsExtensions
|
||||||
[Projectable]
|
[Projectable]
|
||||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global",
|
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global",
|
||||||
Justification = "Projectable chain must have consistent visibility")]
|
Justification = "Projectable chain must have consistent visibility")]
|
||||||
internal static bool FtsQueryPreEscaped(
|
internal static bool FtsQueryPreEscaped(this Note note, string query, bool negated, CaseFilterType caseSensitivity, MatchFilterType matchType) => matchType.Equals(MatchFilterType.Substring)
|
||||||
this Note note, string query, bool negated, CaseFilterType caseSensitivity, MatchFilterType matchType
|
|
||||||
) => matchType.Equals(MatchFilterType.Substring)
|
|
||||||
? caseSensitivity.Equals(CaseFilterType.Sensitive)
|
? caseSensitivity.Equals(CaseFilterType.Sensitive)
|
||||||
? negated
|
? negated
|
||||||
? !EF.Functions.Like(note.Text!, "%" + query + "%", @"\") &&
|
? !EF.Functions.Like(note.Text!, "%" + query + "%", @"\") &&
|
||||||
!EF.Functions.Like(note.Cw!, "%" + query + "%", @"\")
|
!EF.Functions.Like(note.Cw!, "%" + query + "%", @"\") &&
|
||||||
|
!EF.Functions.Like(note.CombinedAltText!, "%" + query + "%", @"\")
|
||||||
: EF.Functions.Like(note.Text!, "%" + query + "%", @"\") ||
|
: EF.Functions.Like(note.Text!, "%" + query + "%", @"\") ||
|
||||||
EF.Functions.Like(note.Cw!, "%" + query + "%", @"\")
|
EF.Functions.Like(note.Cw!, "%" + query + "%", @"\") ||
|
||||||
|
EF.Functions.Like(note.CombinedAltText!, "%" + query + "%", @"\")
|
||||||
: negated
|
: negated
|
||||||
? !EF.Functions.ILike(note.Text!, "%" + query + "%", @"\") &&
|
? !EF.Functions.ILike(note.Text!, "%" + query + "%", @"\") &&
|
||||||
!EF.Functions.ILike(note.Cw!, "%" + query + "%", @"\")
|
!EF.Functions.ILike(note.Cw!, "%" + query + "%", @"\") &&
|
||||||
|
!EF.Functions.ILike(note.CombinedAltText!, "%" + query + "%", @"\")
|
||||||
: EF.Functions.ILike(note.Text!, "%" + query + "%", @"\") ||
|
: EF.Functions.ILike(note.Text!, "%" + query + "%", @"\") ||
|
||||||
EF.Functions.ILike(note.Cw!, "%" + query + "%", @"\")
|
EF.Functions.ILike(note.Cw!, "%" + query + "%", @"\") ||
|
||||||
|
EF.Functions.ILike(note.CombinedAltText!, "%" + query + "%", @"\")
|
||||||
: caseSensitivity.Equals(CaseFilterType.Sensitive)
|
: caseSensitivity.Equals(CaseFilterType.Sensitive)
|
||||||
? negated
|
? negated
|
||||||
? !Regex.IsMatch(note.Text!, "\\y" + query + "\\y") &&
|
? !Regex.IsMatch(note.Text!, "\\y" + query + "\\y") &&
|
||||||
!Regex.IsMatch(note.Cw!, "\\y" + query + "\\y")
|
!Regex.IsMatch(note.Cw!, "\\y" + query + "\\y") &&
|
||||||
|
!Regex.IsMatch(note.CombinedAltText!, "\\y" + query + "\\y")
|
||||||
: Regex.IsMatch(note.Text!, "\\y" + query + "\\y") ||
|
: Regex.IsMatch(note.Text!, "\\y" + query + "\\y") ||
|
||||||
Regex.IsMatch(note.Cw!, "\\y" + query + "\\y")
|
Regex.IsMatch(note.Cw!, "\\y" + query + "\\y") ||
|
||||||
|
Regex.IsMatch(note.CombinedAltText!, "\\y" + query + "\\y")
|
||||||
: negated
|
: negated
|
||||||
? !Regex.IsMatch(note.Text!, "\\y" + query + "\\y", RegexOptions.IgnoreCase) &&
|
? !Regex.IsMatch(note.Text!, "\\y" + query + "\\y", RegexOptions.IgnoreCase) &&
|
||||||
!Regex.IsMatch(note.Cw!, "\\y" + query + "\\y", RegexOptions.IgnoreCase)
|
!Regex.IsMatch(note.Cw!, "\\y" + query + "\\y", RegexOptions.IgnoreCase) &&
|
||||||
|
!Regex.IsMatch(note.CombinedAltText!, "\\y" + query + "\\y", RegexOptions.IgnoreCase)
|
||||||
: Regex.IsMatch(note.Text!, "\\y" + query + "\\y", RegexOptions.IgnoreCase) ||
|
: Regex.IsMatch(note.Text!, "\\y" + query + "\\y", RegexOptions.IgnoreCase) ||
|
||||||
Regex.IsMatch(note.Cw!, "\\y" + query + "\\y", RegexOptions.IgnoreCase);
|
Regex.IsMatch(note.Cw!, "\\y" + query + "\\y", RegexOptions.IgnoreCase) ||
|
||||||
|
Regex.IsMatch(note.CombinedAltText!, "\\y" + query + "\\y", RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
internal static string PreEscapeFtsQuery(string query, MatchFilterType matchType)
|
internal static string PreEscapeFtsQuery(string query, MatchFilterType matchType)
|
||||||
=> matchType.Equals(MatchFilterType.Substring)
|
=> matchType.Equals(MatchFilterType.Substring)
|
||||||
|
|
|
@ -239,6 +239,7 @@ public class NoteService(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var combinedAltText = data.Attachments?.Select(p => p.Comment).Where(c => c != null);
|
||||||
policySvc.CallRewriteHooks(data, IRewritePolicy.HookLocationEnum.PostLogic);
|
policySvc.CallRewriteHooks(data, IRewritePolicy.HookLocationEnum.PostLogic);
|
||||||
|
|
||||||
var note = new Note
|
var note = new Note
|
||||||
|
@ -270,7 +271,8 @@ public class NoteService(
|
||||||
Emojis = data.Emoji ?? [],
|
Emojis = data.Emoji ?? [],
|
||||||
ReplyUri = data.ReplyUri,
|
ReplyUri = data.ReplyUri,
|
||||||
RenoteUri = data.RenoteUri,
|
RenoteUri = data.RenoteUri,
|
||||||
RepliesCollection = data.ASNote?.Replies?.Id
|
RepliesCollection = data.ASNote?.Replies?.Id,
|
||||||
|
CombinedAltText = combinedAltText != null ? string.Join(' ', combinedAltText) : null
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.Poll != null)
|
if (data.Poll != null)
|
||||||
|
@ -594,6 +596,10 @@ public class NoteService(
|
||||||
{
|
{
|
||||||
note.FileIds = fileIds;
|
note.FileIds = fileIds;
|
||||||
note.AttachedFileTypes = data.Attachments?.Select(p => p.Type).ToList() ?? [];
|
note.AttachedFileTypes = data.Attachments?.Select(p => p.Type).ToList() ?? [];
|
||||||
|
|
||||||
|
var combinedAltText = data.Attachments?.Select(p => p.Comment).Where(c => c != null);
|
||||||
|
note.CombinedAltText = combinedAltText != null ? string.Join(' ', combinedAltText) : null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var isPollEdited = false;
|
var isPollEdited = false;
|
||||||
|
|
Loading…
Add table
Reference in a new issue