子查询上的 Ecto.QueryError

cle*_*y00 1 elixir ecto

对于以下查询:

sub_query = from sq in Database.Nestoria,
  distinct: sq.lister_url,
  select: [sq.place_name,
          sq.price,
          sq.price_type],
  where: fragment("cast(to_char(?, 'YYYYMMDD') AS INTEGER) >= (SELECT cast(to_char(max(inserted_at), 'YYYYMMDD') AS INTEGER) - 1 FROM nestoria)", sq.inserted_at),
  where: sq.bedroom_number == 1

query = from un in Database.Underground,
  left_join: ne in subquery(sub_query), on: un.station_name_slug == ne.place_name,
  select: [ un.lines_id,
            un.station_name,
            un.display_name,
            ne.place_name,
            fragment("count(?) as data_count", ne.place_name),
            fragment("Avg(CASE WHEN ? = 'weekly' THEN price * ( 31 / 7 ) ELSE price END) AS avg_monthly_price ", ne.price_type)],
  group_by: [un.lines_id,
            un.station_name,
            un.display_name,
            ne.place_name],
  order_by: [ne.place_name]

output = Repo.all(query)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

** (Ecto.QueryError) subquery must select a source (t), a field (t.field) or a map, got: [&0.place_name(), &0.price(), &0.price_type()]

奇怪的是我已经在一个非常相似的项目中运行它而没有遇到任何问题。所有模式都正常工作,没有任何问题(Repo.all(Nestoria/Underground) 返回正常)。

Dog*_*ert 5

截至当前版本的 Ecto 子查询不能将select列表作为值。即使这以某种方式起作用,您也无法ne.place_name在问题中的查询中执行此操作,因为这ne将是一个列表,而不是地图。

您可以手动选择地图:

select: %{place_name: sq.place_name, price: sq.price, ...}
Run Code Online (Sandbox Code Playgroud)

或使用mapstruct

select: map(sq, [:place_name, :price, :price_type])
# or
select: struct(sq, [:place_name, :price, :price_type])
Run Code Online (Sandbox Code Playgroud)

或者只传递一个字段列表,这相当于struct上面的版本:

select: [:place_name, :price, :price_type]
Run Code Online (Sandbox Code Playgroud)