首页 > 解决方案 > Ecto:如何访问预加载关联的字段

问题描述

我正在尝试获取与friend_referral_code没有关联的用户,或者他们的代码状态为假并且他们也没有使用任何代码。但我无法访问预加载的关联friend_referral_code的字段状态。以下是我的做法:

def get_first_free_invite_users() do
    users =
      list_users()
      |> Repo.preload([:friend_referral_code])
      |> Enum.filter(
        fn u ->
          u.friend_referral_code == [] or u.friend_referral_code["status"] == false and
          Repo.all(from ref in FriendReferralCode,
            where: ref.receiver_id == ^u.id and ref.status == true) == []
        end)
    users
  end

它在u.friend_referral_code.status == false. 我不能加入的原因是 FriendReferralCode 中可能没有特定用户的记录,我想捕获这些用户。这是关联的加载方式:

friend_referral_code: [
      %MyApp.Accounts.FriendReferralCode{
        __meta__: #Ecto.Schema.Metadata<:loaded, "friend_referral_code">,
        challenge: #Ecto.Association.NotLoaded<association :challenge is not loaded>,
        challenge_id: nil,
        code: "RFQTS",
        expiry: 1,
        id: 16021,
        inserted_at: ~N[2021-02-01 11:55:00],
        order: 1,
        prize: #Decimal<3>,
        receiver: #Ecto.Association.NotLoaded<association :receiver is not loaded>,
        receiver_id: 15002,
        state: "create_competition",
        status: false,
        updated_at: ~N[2021-02-01 11:57:20],
        user: #Ecto.Association.NotLoaded<association :user is not loaded>,
        user_id: 15001
      }
    ],

标签: elixirecto

解决方案


它在 u.friend_referral_code.status == false 上引发错误。

那是因为u.friend_referral_code在您的示例中是一个列表。您需要枚举u.friend_referral_code并检查每个状态。

尝试这样的事情。

def get_ref_codes_by_user(id) do
  Repo.all(from ref in FriendReferralCode,
    where: ref.receiver_id == ^u.id and ref.status == true)
end

def filter_referrals([], user_id, acc), do: acc
def filter_referrals([ref, rest], user_id, acc) do
  is_used = 
    ref == [] || ref.status == false && get_ref_codes_by_user(id) == []
  
  new_acc = 
    case is_used do
      true -> acc
      false -> [ref | acc]
    end

  filter_referrals(rest, user_id, new_acc)
end

def get_first_free_invite_users() do
  list_users()
  |> Repo.preload([:friend_referral_code])
  |> Enum.map(
    fn u ->
      filter_referrals(u.friend_referral_code, u.id, [])
    end)
end

这将使您更接近并为您提供 s 列表FriendReferralCode。仔细检查逻辑是否是您想要的。综上所述,您应该能够通过加入来做到这一点。检查此处的文档以及有关连接类型的其他 SO答案。

尝试

Repo.all(from ref in FriendReferralCode,
  right_join users u on ref.user_id =  u.id
    where: ref.status == true)

推荐阅读