Search code examples
c#postgresqlentity-framework-corefull-text-searchnpgsql

Can I set weights on tsvector fields using Npgsql and Entity Framework Core?


I am in the process of setting up full text search on a PostgresSql table, and I am using Entity Framework Core. I have followed the instructions here to set up the generated tsvector column and everything is working as expected.

This is the code that defines the generated column:

  entity.HasGeneratedTsVectorColumn(
                    p => p.SearchVector,
                    "english",
                    p => new
                    {
                        p.Title,
                        p.Description,
                        p.Tags
                    })
                .HasIndex(p => p.SearchVector)
                .HasMethod("GIN");

Now I want to set weights on the columns - achieving the equivalent of the code below - so that the title is weighted more heavily than the other fields

  ALTER TABLE books ADD COLUMN full_text_search_weighted TSVECTOR
    GENERATED ALWAYS AS (
      setweight(to_tsvector('english', coalesce(title, '')), 'A')),
      setweight(to_tsvector('english', coalesce(description, '')), 'B')),
      setweight(to_tsvector('english', coalesce(tags, '')), 'C'))
    ) STORED;

Is there a way to achieve using C#, Npgsql and Entity Framework Core, or will I need to write a fully custom migration?

Answer Thanks to Shay's answer, I managed to this with the following code in the migration:

  entity.Property(p => p.WeightedSearchVector)
                .HasComputedColumnSql(
                    "setweight(to_tsvector('english', coalesce(title, '')), 'A') ||' '|| setweight(to_tsvector('english', coalesce(description, '')), 'B') || ' '|| setweight(to_tsvector('english', coalesce(tags, '')), 'C')", stored: true);
  entity.HasIndex(e => e.WeightedSearchVector).HasMethod("GIN");

Solution

  • No; HasGeneratedTsVectorColumn() really was only meant to be sugar covering the basic scenario; you can drop down to SQL to do any custom configuration you want. However, there's absolutely no need to do this in your migration - EF allows you to configure generated columns with arbitrary SQL via regular Fluent API (see docs).