【问题标题】:How to use a Postgrex Extension?如何使用 Postgrex 扩展?
【发布时间】:2018-05-07 16:08:31
【问题描述】:

我正在尝试使用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}]

这是架构

  schema "branches" do
    field :address, :string
    field :tags, {:array, :string}
    field :document, Postgrex.Extensions.TSVector

    belongs_to :bank, Bank

    timestamps()
  end

这不应该给我一个新的类型TSVector吗?我收到以下错误

** (ArgumentError) invalid or unknown type Postgrex.Extensions.TSVector for field :document

更新

我尝试将架构设置为以下

field :document, {:array, Postgrex.Lexeme}

在从数据库中检索值时,我收到以下错误 ** (UndefinedFunctionError) function Postgrex.Lexeme.type/0 is undefined or private

【问题讨论】:

  • 请显示您的架构。我希望你有像field :document, TSVector 这样的东西,而它应该是完全合格的field :document, Postgrex.Extensions.TSVector
  • @mudasobwa 添加
  • 您是否介意尝试将:tsvector 作为字段类型(正好在您的迁移中)。
  • 根据Ecto Postgres docs,应该是field :document, {:array, Postgrex.Lexeme}
  • 使用上面的,现在得到** (UndefinedFunctionError) function Postgrex.Lexeme.type/0 is undefined or private

标签: elixir phoenix-framework ecto


【解决方案1】:

我遇到了同样的问题。在此拉取请求之后,tsvector 扩展默认包含/加载到 Postgrex:https://github.com/elixir-ecto/postgrex/pull/284,因此没有必要在您的 Project.Repo 配置中添加任何 :extensions 选项。

我在这样的迁移中创建了该列:

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

之后,事实证明您不能简单地将 :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

之后,你可以在你的模块schema中包含这个类型:

schema "diagnoses" do
  field :icd10_code, :string
  field :description, :string
  field :search_tsvector, MyApp.Ecto.Types.TSVectorType

  timestamps_with_deleted_at()
end

我实现了像这样搜索这个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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-14
    • 2018-04-10
    相关资源
    最近更新 更多