【问题标题】:Ecto limit on nested associations嵌套关联的 Ecto 限制
【发布时间】:2021-10-30 01:12:24
【问题描述】:

我在使用Ecto 进行查询时遇到了一些麻烦:

SavedDevice
    - belongs_to Devices
    - belongs_to User
Device
    - has_many SavedDevices
    - has_many DeviceLocations
DeviceLocation
    - belongs_to Devices

我想加载属于 UserSavedDevices,并保存最新的 DeviceLocation

这个解决方案很好用:

  def list_pdevices_locations(user, limit \\ 0) do
    location_query = from(dl in DeviceLocation, order_by: [desc: :inserted_at])
    query =
      from(d in ProvisionedDevice,
        preload: [device_info: [locations: ^location_query]],
        limit: ^limit
      )

    if user.is_admin do
      Repo.all(query)
    else
      Repo.all(from(d in query, where: d.user_id == ^user.id))
    end
  end

但它会加载每个 DeviceLocations。这是一个问题,因为可能有数千个,而我只需要最后一个。

当我将 limit: 1 添加到 location_query 时,它只返回 1 个 DeviceLocation 用于所有 设备 而不是 1 个 Devicelocation 设备

有什么想法吗?

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    我不知道这是否可以在预加载中完成,但您可以使用lateral joins(第 7.2.1.5 节)来实现您想要的。您需要为位置创建子查询:

    location_query =
      from(dl in DeviceLocation,
        where: parent_as(:d_info).id == dl.device_info_id,
        # Unique rows by device_info_id
        distinct: dl.device_info_id,
        # Order by inserted at to get the most recent entry
        order_by: [desc: dl.inserted_at]
      )
    

    然后从 ProvisionedDevice 加入它:

    query = 
      from(pd in ProvisionedDevice,
        inner_join: di as assoc(pd, :device_info),
        # Use the same alias as specified in the subquery
        as: :d_info,
        inner_lateral_join: dl in subquery(location_query),
        on: dl.device_info_id == di.id,
        # You can structure this select any way you like
        select: %{device: pd, info: di, location: dl}
      )
    

    当然,这将不再符合您示例中的返回规范,但您可以发布处理结果以符合您之前的合同(如果需要):

    for %{device: device, info: info, location: location} <- Repo.all(query) do
      info_and_location = %{info | locations: [location]}
      %{device | device_info: info_and_location}
    end
    

    无论哪种方式,查询都会在一个查询中为您提供一台设备及其信息和最近的位置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多