perf(search): trigram indexes for sender/domain filters (#17)
CI / backend (push) Successful in 50s
CI / frontend (push) Successful in 14s
Deploy Staging / deploy (push) Successful in 29s
Security / secrets (push) Successful in 4s
Security / dependencies (push) Successful in 58s
CI / backend (pull_request) Successful in 53s
CI / frontend (pull_request) Successful in 15s
Security / secrets (pull_request) Successful in 4s
Security / dependencies (pull_request) Successful in 56s
CI / backend (push) Successful in 50s
CI / frontend (push) Successful in 14s
Deploy Staging / deploy (push) Successful in 29s
Security / secrets (push) Successful in 4s
Security / dependencies (push) Successful in 58s
CI / backend (pull_request) Successful in 53s
CI / frontend (pull_request) Successful in 15s
Security / secrets (pull_request) Successful in 4s
Security / dependencies (pull_request) Successful in 56s
This commit was merged in pull request #17.
This commit is contained in:
Generated
+758
@@ -0,0 +1,758 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using InboxIntel.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using NpgsqlTypes;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace InboxIntel.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(AppDbContext))]
|
||||
[Migration("20260701235112_TrigramIndexesSenderDomain")]
|
||||
partial class TrigramIndexesSenderDomain
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.4")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "pg_trgm");
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.AnalyticsAggregate", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateOnly>("Day")
|
||||
.HasColumnType("date");
|
||||
|
||||
b.Property<string>("HourHistogramJson")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("NewsletterCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("TotalReceived")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<long>("TotalSizeBytes")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("TotalUnread")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("WithAttachments")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId", "Day")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("analytics_aggregates", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.Attachment", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("EmailId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("FileName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)");
|
||||
|
||||
b.Property<string>("GmailAttachmentId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("MimeType")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("character varying(255)");
|
||||
|
||||
b.Property<long>("SizeBytes")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("EmailId");
|
||||
|
||||
b.HasIndex("UserId", "MimeType");
|
||||
|
||||
b.ToTable("attachments", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.Email", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("BodyText")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Category")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("GmailMessageId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<bool>("HasAttachments")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("HasListUnsubscribe")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsImportant")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsInInbox")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsStarred")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsTrashed")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsUnread")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("ListUnsubscribeRaw")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<DateTimeOffset?>("ReceivedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<NpgsqlTsVector>("SearchVector")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("tsvector")
|
||||
.HasComputedColumnSql("setweight(to_tsvector('english', coalesce(\"Subject\",'')), 'A') || setweight(to_tsvector('english', coalesce(\"BodyText\",'')), 'B')", true);
|
||||
|
||||
b.Property<Guid>("SenderId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("SentAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long>("SizeEstimateBytes")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Snippet")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("Subject")
|
||||
.HasMaxLength(1024)
|
||||
.HasColumnType("character varying(1024)");
|
||||
|
||||
b.Property<bool>("SupportsOneClickUnsubscribe")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<Guid>("ThreadId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SearchVector");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("SearchVector"), "GIN");
|
||||
|
||||
b.HasIndex("SenderId");
|
||||
|
||||
b.HasIndex("ThreadId");
|
||||
|
||||
b.HasIndex("UserId", "Category");
|
||||
|
||||
b.HasIndex("UserId", "GmailMessageId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserId", "IsInInbox");
|
||||
|
||||
b.HasIndex("UserId", "IsUnread");
|
||||
|
||||
b.HasIndex("UserId", "SenderId");
|
||||
|
||||
b.HasIndex("UserId", "SentAtUtc");
|
||||
|
||||
b.ToTable("emails", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.EmailLabel", b =>
|
||||
{
|
||||
b.Property<Guid>("EmailId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("LabelId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("EmailId", "LabelId");
|
||||
|
||||
b.HasIndex("LabelId");
|
||||
|
||||
b.ToTable("email_labels", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.Label", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("ColorHex")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("GmailLabelId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("character varying(255)");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId", "GmailLabelId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("labels", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.MailDomain", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("EmailCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("IsBulkSender")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("character varying(255)");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Name"), "gin");
|
||||
NpgsqlIndexBuilderExtensions.HasOperators(b.HasIndex("Name"), new[] { "gin_trgm_ops" });
|
||||
|
||||
b.HasIndex("UserId", "Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("domains", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.MailThread", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset?>("FirstMessageUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("GmailThreadId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastMessageUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("MessageCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Snippet")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Subject")
|
||||
.HasMaxLength(1024)
|
||||
.HasColumnType("character varying(1024)");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId", "GmailThreadId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("threads", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.Sender", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.IsRequired()
|
||||
.HasMaxLength(320)
|
||||
.HasColumnType("character varying(320)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("DisplayName")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("character varying(255)");
|
||||
|
||||
b.Property<Guid>("DomainId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("EmailCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("HasUnsubscribe")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastReceivedUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long>("TotalSizeBytes")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("UnreadCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Address");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Address"), "gin");
|
||||
NpgsqlIndexBuilderExtensions.HasOperators(b.HasIndex("Address"), new[] { "gin_trgm_ops" });
|
||||
|
||||
b.HasIndex("DisplayName");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("DisplayName"), "gin");
|
||||
NpgsqlIndexBuilderExtensions.HasOperators(b.HasIndex("DisplayName"), new[] { "gin_trgm_ops" });
|
||||
|
||||
b.HasIndex("DomainId");
|
||||
|
||||
b.HasIndex("UserId", "Address")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserId", "EmailCount");
|
||||
|
||||
b.ToTable("senders", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.SyncState", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset?>("CompletedUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("ConsecutiveFailures")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("LastError")
|
||||
.HasMaxLength(4000)
|
||||
.HasColumnType("character varying(4000)");
|
||||
|
||||
b.Property<string>("LastHistoryId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastSuccessfulSyncUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("LastSyncType")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MessagesProcessed")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("ResumePageToken")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset?>("StartedUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("TotalMessagesEstimate")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("sync_states", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.UnsubscribeItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<double>("Confidence")
|
||||
.HasColumnType("double precision");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("EmailCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastAttemptUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("Method")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("ResultMessage")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("SenderId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("UnsubscribeTarget")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SenderId");
|
||||
|
||||
b.HasIndex("UserId", "SenderId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("unsubscribe_items", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset?>("AccessTokenExpiresAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<bool>("DigestEnabled")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("DisplayName")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasMaxLength(320)
|
||||
.HasColumnType("character varying(320)");
|
||||
|
||||
b.Property<byte[]>("EncryptedRefreshToken")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("GoogleSubjectId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastDigestSentUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastLoginUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("PictureUrl")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Email")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("GoogleSubjectId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("users", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.WidgetLayout", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("H")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("SettingsJson")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTimeOffset?>("UpdatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("Visible")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<int>("W")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("WidgetKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<int>("X")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Y")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId", "WidgetKey")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("widget_layouts", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.Attachment", b =>
|
||||
{
|
||||
b.HasOne("InboxIntel.Domain.Entities.Email", "Email")
|
||||
.WithMany("Attachments")
|
||||
.HasForeignKey("EmailId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Email");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.Email", b =>
|
||||
{
|
||||
b.HasOne("InboxIntel.Domain.Entities.Sender", "Sender")
|
||||
.WithMany("Emails")
|
||||
.HasForeignKey("SenderId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("InboxIntel.Domain.Entities.MailThread", "Thread")
|
||||
.WithMany("Emails")
|
||||
.HasForeignKey("ThreadId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("InboxIntel.Domain.Entities.User", null)
|
||||
.WithMany("Emails")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Sender");
|
||||
|
||||
b.Navigation("Thread");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.EmailLabel", b =>
|
||||
{
|
||||
b.HasOne("InboxIntel.Domain.Entities.Email", "Email")
|
||||
.WithMany("EmailLabels")
|
||||
.HasForeignKey("EmailId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("InboxIntel.Domain.Entities.Label", "Label")
|
||||
.WithMany("EmailLabels")
|
||||
.HasForeignKey("LabelId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Email");
|
||||
|
||||
b.Navigation("Label");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.Sender", b =>
|
||||
{
|
||||
b.HasOne("InboxIntel.Domain.Entities.MailDomain", "Domain")
|
||||
.WithMany("Senders")
|
||||
.HasForeignKey("DomainId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Domain");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.UnsubscribeItem", b =>
|
||||
{
|
||||
b.HasOne("InboxIntel.Domain.Entities.Sender", "Sender")
|
||||
.WithMany()
|
||||
.HasForeignKey("SenderId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Sender");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.WidgetLayout", b =>
|
||||
{
|
||||
b.HasOne("InboxIntel.Domain.Entities.User", null)
|
||||
.WithMany("WidgetLayouts")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.Email", b =>
|
||||
{
|
||||
b.Navigation("Attachments");
|
||||
|
||||
b.Navigation("EmailLabels");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.Label", b =>
|
||||
{
|
||||
b.Navigation("EmailLabels");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.MailDomain", b =>
|
||||
{
|
||||
b.Navigation("Senders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.MailThread", b =>
|
||||
{
|
||||
b.Navigation("Emails");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.Sender", b =>
|
||||
{
|
||||
b.Navigation("Emails");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("Emails");
|
||||
|
||||
b.Navigation("WidgetLayouts");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace InboxIntel.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class TrigramIndexesSenderDomain : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_senders_Address",
|
||||
table: "senders",
|
||||
column: "Address")
|
||||
.Annotation("Npgsql:IndexMethod", "gin")
|
||||
.Annotation("Npgsql:IndexOperators", new[] { "gin_trgm_ops" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_senders_DisplayName",
|
||||
table: "senders",
|
||||
column: "DisplayName")
|
||||
.Annotation("Npgsql:IndexMethod", "gin")
|
||||
.Annotation("Npgsql:IndexOperators", new[] { "gin_trgm_ops" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_domains_Name",
|
||||
table: "domains",
|
||||
column: "Name")
|
||||
.Annotation("Npgsql:IndexMethod", "gin")
|
||||
.Annotation("Npgsql:IndexOperators", new[] { "gin_trgm_ops" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_senders_Address",
|
||||
table: "senders");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_senders_DisplayName",
|
||||
table: "senders");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_domains_Name",
|
||||
table: "domains");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,6 +301,11 @@ namespace InboxIntel.Infrastructure.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Name"), "gin");
|
||||
NpgsqlIndexBuilderExtensions.HasOperators(b.HasIndex("Name"), new[] { "gin_trgm_ops" });
|
||||
|
||||
b.HasIndex("UserId", "Name")
|
||||
.IsUnique();
|
||||
|
||||
@@ -395,6 +400,16 @@ namespace InboxIntel.Infrastructure.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Address");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Address"), "gin");
|
||||
NpgsqlIndexBuilderExtensions.HasOperators(b.HasIndex("Address"), new[] { "gin_trgm_ops" });
|
||||
|
||||
b.HasIndex("DisplayName");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("DisplayName"), "gin");
|
||||
NpgsqlIndexBuilderExtensions.HasOperators(b.HasIndex("DisplayName"), new[] { "gin_trgm_ops" });
|
||||
|
||||
b.HasIndex("DomainId");
|
||||
|
||||
b.HasIndex("UserId", "Address")
|
||||
|
||||
@@ -75,6 +75,16 @@ public class AppDbContext : DbContext, IAppDbContext
|
||||
"setweight(to_tsvector('english', coalesce(\"BodyText\",'')), 'B')",
|
||||
stored: true);
|
||||
modelBuilder.Entity<Email>().HasIndex(e => e.SearchVector).HasMethod("GIN");
|
||||
|
||||
// Trigram GIN indexes so the sender/domain `.Contains()` filters in SearchService
|
||||
// (which translate to `LIKE '%x%'`, non-sargable on a btree) become index-accelerated.
|
||||
// Needs pg_trgm (enabled by the EnablePgTrgm migration).
|
||||
modelBuilder.Entity<Sender>().HasIndex(s => s.Address)
|
||||
.HasMethod("gin").HasOperators("gin_trgm_ops");
|
||||
modelBuilder.Entity<Sender>().HasIndex(s => s.DisplayName)
|
||||
.HasMethod("gin").HasOperators("gin_trgm_ops");
|
||||
modelBuilder.Entity<MailDomain>().HasIndex(d => d.Name)
|
||||
.HasMethod("gin").HasOperators("gin_trgm_ops");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user