You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elixir中如何使用has_one关联非主键列?

问题描述

我有一张user_reward_entries表,其Ecto Schema定义如下:

@primary_key false
schema "user_reward_entries" do
  field(:id, Ecto.UUID, primary_key: true, read_after_writes: true)
  field(:amount, :integer)
  ...

  belongs_to(:transaction, Transaction)
  belongs_to(:user, User)

  timestamps()
end

该表的复合主键由id和user_id组成,通过belongs_to关联了transactions表。

现在我尝试在accounts_transactions表的Schema中反向关联user_reward_entries表,Schema定义如下:

@primary_key false
schema "accounts_transactions" do
  field(:id, Ecto.UUID, primary_key: true, read_after_writes: true)

  ...

  has_one :user_reward_entry, UserRewardEntry

  field(:completed_at, :utc_datetime_usec)

  timestamps()
end

执行时遇到错误:

need to set :references option for association :user_reward_entry when schema has no primary key

随后我尝试设置:references选项:

has_one :user_reward_entry, UserRewardEntry,
  references: UserRewardEntry,
  foreign_key: :transaction_id

但又出现错误:

schema does not have the field SharedDb.Models.Rewards.UserRewardEntry used by association :user_reward_entry, please set the :references option accordingly

我还尝试过:

has_one :user_reward_entry, UserRewardEntry,
  references: UserRewardEntry,
  foreign_key: :transaction

但得到相同的错误,请问正确的做法是什么?


解决方法

核心错误是对:references参数的理解偏差:

  • :references需要指定当前Schema(即accounts_transactions对应的Transaction Schema)中的字段名,这个字段是被关联表(user_reward_entries)外键的引用目标。
  • 你之前把references设成了UserRewardEntry模块,完全不符合Ecto的参数要求。

正确的关联写法如下:

has_one :user_reward_entry, UserRewardEntry,
  foreign_key: :transaction_id,
  references: :id

参数说明

  • foreign_key: :transaction_id:指定user_reward_entries表中关联当前表的外键字段(对应belongs_to(:transaction, Transaction)自动生成的外键)。
  • references: :id:指定当前表(accounts_transactions)中被外键引用的主键字段,即Transaction的id字段。

补充说明

虽然user_reward_entries用了复合主键,但当前场景是建立“交易-奖励条目”的一对一关联,仅需基于transaction_id即可完成约束。如果后续需要基于复合主键做更严格的关联,可以在关联中添加where条件限制user_id,但当前写法已足够解决问题。


内容的提问来源于stack exchange,提问作者jhamm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 23:40:38