Added primitive search mechanism in backend.

Began implementing search mechanism for frontend.
This commit is contained in:
2021-08-05 01:22:19 -05:00
parent f71758ca69
commit c94ea4a624
56 changed files with 1623 additions and 490 deletions

View File

@@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.Extensions.Localization;
using Props.Models;
using Props.Models.Search;
using Props.Models.User;
@@ -16,8 +17,10 @@ namespace Props.Data
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
DbSet<SearchOutline> SearchOutlines { get; set; }
DbSet<ProductListingInfo> TrackedListings { get; set; }
public DbSet<QueryWordInfo> Keywords { get; set; }
public DbSet<ProductListingInfo> ProductListingInfos { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
@@ -40,7 +43,7 @@ namespace Props.Data
);
modelBuilder.Entity<SearchOutline>()
.Property(e => e.Disabled)
.Property(e => e.Enabled)
.HasConversion(
v => JsonSerializer.Serialize(v, null),
v => JsonSerializer.Deserialize<SearchOutline.ShopsDisabled>(v, null),
@@ -50,6 +53,7 @@ namespace Props.Data
c => c.Copy()
)
);
modelBuilder.Entity<SearchOutline>()
.Property(e => e.Filters)
.HasConversion(

View File

@@ -9,7 +9,7 @@ using Props.Data;
namespace Props.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20210724073427_InitialCreate")]
[Migration("20210805055109_InitialCreate")]
partial class InitialCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -188,18 +188,36 @@ namespace Props.Data.Migrations
b.Property<DateTime>("LastUpdated")
.HasColumnType("TEXT");
b.Property<string>("OriginName")
.HasColumnType("TEXT");
b.Property<string>("ProductName")
.HasColumnType("TEXT");
b.Property<string>("ProductUrl")
.HasColumnType("TEXT");
b.Property<string>("ShopName")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("TrackedListings");
b.ToTable("ProductListingInfos");
});
modelBuilder.Entity("Props.Models.Search.QueryWordInfo", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<uint>("Hits")
.HasColumnType("INTEGER");
b.Property<string>("Word")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Keywords");
});
modelBuilder.Entity("Props.Models.Search.SearchOutline", b =>
@@ -212,18 +230,27 @@ namespace Props.Data.Migrations
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Disabled")
b.Property<string>("Enabled")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Filters")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("SearchOutlinePreferencesId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ApplicationUserId");
b.ToTable("SearchOutlines");
b.HasIndex("SearchOutlinePreferencesId");
b.ToTable("SearchOutline");
});
modelBuilder.Entity("Props.Models.User.ApplicationUser", b =>
@@ -290,6 +317,29 @@ namespace Props.Data.Migrations
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Props.Models.User.SearchOutlinePreferences", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("ActiveSearchOutlineId")
.HasColumnType("INTEGER");
b.Property<string>("ApplicationUserId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ActiveSearchOutlineId");
b.HasIndex("ApplicationUserId")
.IsUnique();
b.ToTable("SearchOutlinePreferences");
});
modelBuilder.Entity("Props.Shared.Models.User.ApplicationPreferences", b =>
{
b.Property<int>("Id")
@@ -314,6 +364,21 @@ namespace Props.Data.Migrations
b.ToTable("ApplicationPreferences");
});
modelBuilder.Entity("QueryWordInfoQueryWordInfo", b =>
{
b.Property<int>("FollowingId")
.HasColumnType("INTEGER");
b.Property<int>("PrecedingId")
.HasColumnType("INTEGER");
b.HasKey("FollowingId", "PrecedingId");
b.HasIndex("PrecedingId");
b.ToTable("QueryWordInfoQueryWordInfo");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
@@ -379,11 +444,32 @@ namespace Props.Data.Migrations
modelBuilder.Entity("Props.Models.Search.SearchOutline", b =>
{
b.HasOne("Props.Models.User.ApplicationUser", "ApplicationUser")
.WithMany("SearchOutlines")
.WithMany()
.HasForeignKey("ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Props.Models.User.SearchOutlinePreferences", null)
.WithMany("SearchOutlines")
.HasForeignKey("SearchOutlinePreferencesId");
b.Navigation("ApplicationUser");
});
modelBuilder.Entity("Props.Models.User.SearchOutlinePreferences", b =>
{
b.HasOne("Props.Models.Search.SearchOutline", "ActiveSearchOutline")
.WithMany()
.HasForeignKey("ActiveSearchOutlineId");
b.HasOne("Props.Models.User.ApplicationUser", "ApplicationUser")
.WithOne("searchOutlinePreferences")
.HasForeignKey("Props.Models.User.SearchOutlinePreferences", "ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ActiveSearchOutline");
b.Navigation("ApplicationUser");
});
@@ -398,6 +484,21 @@ namespace Props.Data.Migrations
b.Navigation("ApplicationUser");
});
modelBuilder.Entity("QueryWordInfoQueryWordInfo", b =>
{
b.HasOne("Props.Models.Search.QueryWordInfo", null)
.WithMany()
.HasForeignKey("FollowingId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Props.Models.Search.QueryWordInfo", null)
.WithMany()
.HasForeignKey("PrecedingId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Props.Models.User.ApplicationUser", b =>
{
b.Navigation("ApplicationPreferences")
@@ -406,6 +507,12 @@ namespace Props.Data.Migrations
b.Navigation("ResultsPreferences")
.IsRequired();
b.Navigation("searchOutlinePreferences")
.IsRequired();
});
modelBuilder.Entity("Props.Models.User.SearchOutlinePreferences", b =>
{
b.Navigation("SearchOutlines");
});
#pragma warning restore 612, 618

View File

@@ -47,12 +47,26 @@ namespace Props.Data.Migrations
});
migrationBuilder.CreateTable(
name: "TrackedListings",
name: "Keywords",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
OriginName = table.Column<string>(type: "TEXT", nullable: true),
Word = table.Column<string>(type: "TEXT", nullable: false),
Hits = table.Column<uint>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Keywords", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ProductListingInfos",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ShopName = table.Column<string>(type: "TEXT", nullable: true),
Hits = table.Column<uint>(type: "INTEGER", nullable: false),
LastUpdated = table.Column<DateTime>(type: "TEXT", nullable: false),
ProductUrl = table.Column<string>(type: "TEXT", nullable: true),
@@ -60,7 +74,7 @@ namespace Props.Data.Migrations
},
constraints: table =>
{
table.PrimaryKey("PK_TrackedListings", x => x.Id);
table.PrimaryKey("PK_ProductListingInfos", x => x.Id);
});
migrationBuilder.CreateTable(
@@ -212,26 +226,78 @@ namespace Props.Data.Migrations
});
migrationBuilder.CreateTable(
name: "SearchOutlines",
name: "QueryWordInfoQueryWordInfo",
columns: table => new
{
FollowingId = table.Column<int>(type: "INTEGER", nullable: false),
PrecedingId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_QueryWordInfoQueryWordInfo", x => new { x.FollowingId, x.PrecedingId });
table.ForeignKey(
name: "FK_QueryWordInfoQueryWordInfo_Keywords_FollowingId",
column: x => x.FollowingId,
principalTable: "Keywords",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_QueryWordInfoQueryWordInfo_Keywords_PrecedingId",
column: x => x.PrecedingId,
principalTable: "Keywords",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "SearchOutline",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: false),
Name = table.Column<string>(type: "TEXT", nullable: false),
Filters = table.Column<string>(type: "TEXT", nullable: true),
Disabled = table.Column<string>(type: "TEXT", nullable: false)
Enabled = table.Column<string>(type: "TEXT", nullable: false),
SearchOutlinePreferencesId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_SearchOutlines", x => x.Id);
table.PrimaryKey("PK_SearchOutline", x => x.Id);
table.ForeignKey(
name: "FK_SearchOutlines_AspNetUsers_ApplicationUserId",
name: "FK_SearchOutline_AspNetUsers_ApplicationUserId",
column: x => x.ApplicationUserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "SearchOutlinePreferences",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: false),
ActiveSearchOutlineId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_SearchOutlinePreferences", x => x.Id);
table.ForeignKey(
name: "FK_SearchOutlinePreferences_AspNetUsers_ApplicationUserId",
column: x => x.ApplicationUserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_SearchOutlinePreferences_SearchOutline_ActiveSearchOutlineId",
column: x => x.ActiveSearchOutlineId,
principalTable: "SearchOutline",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_ApplicationPreferences_ApplicationUserId",
table: "ApplicationPreferences",
@@ -275,6 +341,11 @@ namespace Props.Data.Migrations
column: "NormalizedUserName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_QueryWordInfoQueryWordInfo_PrecedingId",
table: "QueryWordInfoQueryWordInfo",
column: "PrecedingId");
migrationBuilder.CreateIndex(
name: "IX_ResultsPreferences_ApplicationUserId",
table: "ResultsPreferences",
@@ -282,13 +353,49 @@ namespace Props.Data.Migrations
unique: true);
migrationBuilder.CreateIndex(
name: "IX_SearchOutlines_ApplicationUserId",
table: "SearchOutlines",
name: "IX_SearchOutline_ApplicationUserId",
table: "SearchOutline",
column: "ApplicationUserId");
migrationBuilder.CreateIndex(
name: "IX_SearchOutline_SearchOutlinePreferencesId",
table: "SearchOutline",
column: "SearchOutlinePreferencesId");
migrationBuilder.CreateIndex(
name: "IX_SearchOutlinePreferences_ActiveSearchOutlineId",
table: "SearchOutlinePreferences",
column: "ActiveSearchOutlineId");
migrationBuilder.CreateIndex(
name: "IX_SearchOutlinePreferences_ApplicationUserId",
table: "SearchOutlinePreferences",
column: "ApplicationUserId",
unique: true);
migrationBuilder.AddForeignKey(
name: "FK_SearchOutline_SearchOutlinePreferences_SearchOutlinePreferencesId",
table: "SearchOutline",
column: "SearchOutlinePreferencesId",
principalTable: "SearchOutlinePreferences",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_SearchOutline_AspNetUsers_ApplicationUserId",
table: "SearchOutline");
migrationBuilder.DropForeignKey(
name: "FK_SearchOutlinePreferences_AspNetUsers_ApplicationUserId",
table: "SearchOutlinePreferences");
migrationBuilder.DropForeignKey(
name: "FK_SearchOutline_SearchOutlinePreferences_SearchOutlinePreferencesId",
table: "SearchOutline");
migrationBuilder.DropTable(
name: "ApplicationPreferences");
@@ -307,20 +414,29 @@ namespace Props.Data.Migrations
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "ProductListingInfos");
migrationBuilder.DropTable(
name: "QueryWordInfoQueryWordInfo");
migrationBuilder.DropTable(
name: "ResultsPreferences");
migrationBuilder.DropTable(
name: "SearchOutlines");
migrationBuilder.DropTable(
name: "TrackedListings");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "Keywords");
migrationBuilder.DropTable(
name: "AspNetUsers");
migrationBuilder.DropTable(
name: "SearchOutlinePreferences");
migrationBuilder.DropTable(
name: "SearchOutline");
}
}
}

View File

@@ -186,18 +186,36 @@ namespace Props.Data.Migrations
b.Property<DateTime>("LastUpdated")
.HasColumnType("TEXT");
b.Property<string>("OriginName")
.HasColumnType("TEXT");
b.Property<string>("ProductName")
.HasColumnType("TEXT");
b.Property<string>("ProductUrl")
.HasColumnType("TEXT");
b.Property<string>("ShopName")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("TrackedListings");
b.ToTable("ProductListingInfos");
});
modelBuilder.Entity("Props.Models.Search.QueryWordInfo", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<uint>("Hits")
.HasColumnType("INTEGER");
b.Property<string>("Word")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Keywords");
});
modelBuilder.Entity("Props.Models.Search.SearchOutline", b =>
@@ -210,18 +228,27 @@ namespace Props.Data.Migrations
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Disabled")
b.Property<string>("Enabled")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Filters")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("SearchOutlinePreferencesId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ApplicationUserId");
b.ToTable("SearchOutlines");
b.HasIndex("SearchOutlinePreferencesId");
b.ToTable("SearchOutline");
});
modelBuilder.Entity("Props.Models.User.ApplicationUser", b =>
@@ -288,6 +315,29 @@ namespace Props.Data.Migrations
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Props.Models.User.SearchOutlinePreferences", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("ActiveSearchOutlineId")
.HasColumnType("INTEGER");
b.Property<string>("ApplicationUserId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ActiveSearchOutlineId");
b.HasIndex("ApplicationUserId")
.IsUnique();
b.ToTable("SearchOutlinePreferences");
});
modelBuilder.Entity("Props.Shared.Models.User.ApplicationPreferences", b =>
{
b.Property<int>("Id")
@@ -312,6 +362,21 @@ namespace Props.Data.Migrations
b.ToTable("ApplicationPreferences");
});
modelBuilder.Entity("QueryWordInfoQueryWordInfo", b =>
{
b.Property<int>("FollowingId")
.HasColumnType("INTEGER");
b.Property<int>("PrecedingId")
.HasColumnType("INTEGER");
b.HasKey("FollowingId", "PrecedingId");
b.HasIndex("PrecedingId");
b.ToTable("QueryWordInfoQueryWordInfo");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
@@ -377,11 +442,32 @@ namespace Props.Data.Migrations
modelBuilder.Entity("Props.Models.Search.SearchOutline", b =>
{
b.HasOne("Props.Models.User.ApplicationUser", "ApplicationUser")
.WithMany("SearchOutlines")
.WithMany()
.HasForeignKey("ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Props.Models.User.SearchOutlinePreferences", null)
.WithMany("SearchOutlines")
.HasForeignKey("SearchOutlinePreferencesId");
b.Navigation("ApplicationUser");
});
modelBuilder.Entity("Props.Models.User.SearchOutlinePreferences", b =>
{
b.HasOne("Props.Models.Search.SearchOutline", "ActiveSearchOutline")
.WithMany()
.HasForeignKey("ActiveSearchOutlineId");
b.HasOne("Props.Models.User.ApplicationUser", "ApplicationUser")
.WithOne("searchOutlinePreferences")
.HasForeignKey("Props.Models.User.SearchOutlinePreferences", "ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ActiveSearchOutline");
b.Navigation("ApplicationUser");
});
@@ -396,6 +482,21 @@ namespace Props.Data.Migrations
b.Navigation("ApplicationUser");
});
modelBuilder.Entity("QueryWordInfoQueryWordInfo", b =>
{
b.HasOne("Props.Models.Search.QueryWordInfo", null)
.WithMany()
.HasForeignKey("FollowingId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Props.Models.Search.QueryWordInfo", null)
.WithMany()
.HasForeignKey("PrecedingId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Props.Models.User.ApplicationUser", b =>
{
b.Navigation("ApplicationPreferences")
@@ -404,6 +505,12 @@ namespace Props.Data.Migrations
b.Navigation("ResultsPreferences")
.IsRequired();
b.Navigation("searchOutlinePreferences")
.IsRequired();
});
modelBuilder.Entity("Props.Models.User.SearchOutlinePreferences", b =>
{
b.Navigation("SearchOutlines");
});
#pragma warning restore 612, 618