ts_vector_update_trigger和postgresql / npgsql + EFCore中的JSONB列

时间:2019-08-09 11:06:30

标签: c# postgresql entity-framework-core npgsql jsonb

在EFCore + npgsql中,使用postgresql 10,我想创建一个tsvector列以允许对模型中某些字段进行全文搜索:

public class MyModel
{
  public string Title { get; set; }

  public string Description { get; set; }

  [Column(TypeName = "jsonb")]
  public string JSON { get; set; }
}

我希望全文搜索包含JSONB列中的值,因此根据npgsql docs,我将模型更新为:

public class MyModel
{
  public string Title { get; set; }

  public string Description { get; set; }

  [Column(TypeName = "jsonb")]
  public string JSON { get; set; }

  public NpgsqlTsVector SearchVector { get; set; }
}

在我的数据库上下文中的OnModelCreating中添加以下索引:

  modelBuilder.Entity<MyModel>(m =>
  {
    // create some other indexes
    m.HasIndex(e => new { e.SearchVector }).ForNpgsqlHasMethod("GIN");
  });

然后创建迁移并根据文档进行编辑以获取以下方法:

protected override void Up(MigrationBuilder migrationBuilder)
{
  migrationBuilder.AddColumn<NpgsqlTsVector>(
    name: "SearchVector",
    table: "MyModels",
    nullable: true);

  migrationBuilder.CreateIndex(
    name: "IX_MyModels_SearchVector",
    table: "MyModels",
    column: "SearchVector")
    .Annotation("Npgsql:IndexMethod", "GIN");

  migrationBuilder.Sql(
    @"CREATE TRIGGER my_model_search_vector_update BEFORE INSERT OR UPDATE
    ON ""MyModels"" FOR EACH ROW EXECUTE PROCEDURE
    tsvector_update_trigger(""SearchVector"", 'pg_catalog.english', ""Title"", ""Description"", ""JSON"");");

  // I am updating an existing table, so:
  migrationBuilder.Sql("UPDATE \"MyModels\" SET \"Title\" = \"Title\";");
}

protected override void Down(MigrationBuilder migrationBuilder)
{
  migrationBuilder.DropIndex(
    name: "IX_MyModels_SearchVector",
    table: "MyModels");

  migrationBuilder.DropColumn(
    name: "SearchVector",
    table: "MyModels");

  migrationBuilder.Sql("DROP TRIGGER my_model_search_vector_update");
}

但是毕竟,在应用更新数据库时,我看到:

Failed executing DbCommand (50ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
UPDATE "MyModels" SET "Title" = "Title";
Npgsql.PostgresException: column "JSON" is not of a character type

我认为这是因为JSONB列是二进制数据。是否有可能实现我的期望?我对Postgresql,npgsql和EFCore比较陌生。

1 个答案:

答案 0 :(得分:0)

我非常确定您不能在PostgreSQL jsonb上进行全文搜索,因为正如您所写的那样,它不是文本类型。有一个小的变化,即使用json可以正常工作-因为这是文本存储-但这种类型更接近简单的text,并且没有提供二进制jsonb的许多优点。 / p>

但是,jsonb取决于您要做什么,因此具有很多搜索功能(SQL / JSON JSONPATH也包含在PostgreSQL 12中)。该功能当前尚未在EF Core中进行映射,但这并不能真正阻止您通过原始SQL使用它。