cod*_*hal 2 elixir ecto phoenix-framework
我正在尝试使用Postgrex提供的 tsvector 扩展。但我如何在我的 Phoeinx 项目中实际使用它呢?这是我在 dev.exs 中的设置
config :project, Project.Repo,
adapter: Ecto.Adapters.Postgres,
username: "postgres",
password: "postgres",
database: "project_dev",
hostname: "localhost",
pool_size: 10,
extensions: [{Postgrex.Extensions.TSVector}]
Run Code Online (Sandbox Code Playgroud)
这是架构
schema "branches" do
field :address, :string
field :tags, {:array, :string}
field :document, Postgrex.Extensions.TSVector
belongs_to :bank, Bank
timestamps()
end
Run Code Online (Sandbox Code Playgroud)
这不应该给我一个新类型吗TSVector?我收到以下错误
** (ArgumentError) invalid or unknown type Postgrex.Extensions.TSVector for field :document
Run Code Online (Sandbox Code Playgroud)
更新
我尝试将架构设置为以下
field :document, {:array, Postgrex.Lexeme}
Run Code Online (Sandbox Code Playgroud)
从数据库检索值时出现以下错误
** (UndefinedFunctionError) function Postgrex.Lexeme.type/0 is undefined or private
小智 7
我遇到了同样的问题。tsvector在此拉取请求之后,默认情况下,Postgrex 会包含/加载该扩展: https://github.com/elixir-ecto/postgrex/pull/284,因此无需:extensions在配置中添加任何选项Project.Repo。
我在迁移中创建了这样的列:
def change do
alter table(:diagnoses) do
add :search_tsvector, :tsvector
end
execute "UPDATE diagnoses SET search_tsvector = to_tsvector('english', concat_ws(' ', description, icd10_code))"
create index(:diagnoses, [:search_tsvector], using: :gin)
end
Run Code Online (Sandbox Code Playgroud)
之后,事实证明您不能简单地添加:tsvector到模块架构中,因为不:tsvector Ecto存在类型(Postgrex由于扩展,只有类型)。
要在我的架构中使用这个新列,我需要添加一个Ecto仅包含默认样板定义的自定义类型:
defmodule MyApp.Ecto.Types.TSVectorType do
@behaviour Ecto.Type
def type, do: :tsvector
def cast(tsvector), do: {:ok, tsvector}
def load(tsvector), do: {:ok, tsvector}
def dump(tsvector), do: {:ok, tsvector}
end
Run Code Online (Sandbox Code Playgroud)
之后,您可以将此类型包含在您的模块中schema:
schema "diagnoses" do
field :icd10_code, :string
field :description, :string
field :search_tsvector, MyApp.Ecto.Types.TSVectorType
timestamps_with_deleted_at()
end
Run Code Online (Sandbox Code Playgroud)
我tsvector像这样实现了该字段的搜索:
defp filter_by(query, :search_string, %{search_string: search_string} = args) do
tsquery_string = StringHelpers.to_tsquery_string(search_string)
from d in query,
where: fragment("? @@ to_tsquery('english', ?)", d.search_tsvector, ^tsquery_string)
end
Run Code Online (Sandbox Code Playgroud)