简体   繁体   中英

PgSQL - to_tsquery and JOINS leads to Error in Rails

I have the following query:

query = param.tag_list.join("|")

title = "ts_headline(title, query) AS title" 
rank = "ts_rank_cd(tsv, query) AS rank"

Job.select(
  [
    title, rank, :starts_at, :slug, :job_position_id, :id, :city_id,
    :company_office_id
  ]
).from(
  "jobs, to_tsquery('english', '#{query}') AS query"
).where(
  "tsv @@ query AND enabled = true"
).with_position.with_city.with_office.order(
  "rank DESC, starts_at DESC"
).limit(limit)

The with_* scopes just do an includes on positions, city, office. Not more.

This leads to Arel making a query that produces an error:

ActiveRecord::StatementInvalid - PG::Error: ERROR: invalid reference to FROM-clause entry for table "jobs" LINE 1: ...ER JOIN "job_positions" ON "job_positions"."id" = "jobs"."jo... ^ HINT: There is an entry for table "jobs", but it cannot be referenced from this part of the query.

This is most likely related to the problem of mixing implicit and explicit JOINS. See also this ERROR: invalid reference to FROM-clause

The thing is that I don't know how to rewrite the query with the to_tsquery so that it works?

Muchas gracias in advance for any idea

UPDATE

Here the exact query that is produced by Arel in the end. The error refers to the jobs.job_position_id from the first LEFT OUTER JOIN

SELECT  
    ...
FROM 
    jobs, to_tsquery('english', 'coffeescript|backbone.js|javascript|node.js') AS query 
LEFT OUTER JOIN 
    "job_positions" ON "job_positions"."id" = "jobs"."job_position_id" 
LEFT OUTER JOIN 
    "cities" ON "cities"."id" = "jobs"."city_id" 
LEFT OUTER JOIN 
    "company_offices" ON "company_offices"."id" = "jobs"."company_office_id" 
LEFT OUTER JOIN 
    "companies" ON "companies"."id" = "company_offices"."company_id" 
WHERE 
    (tsv @@ query AND enabled = true) 
ORDER BY 
    rank DESC, starts_at DESC 
LIMIT 9

It's a bit hard to tell where the error is coming from exactly without the SQL you're actually generating, but you're almost certainly referencing jobs in a subquery that is at the same level as jobs in the query tree.

Basically, the construct that won't work is the following:

select ...
from foo, (select ... from bar where bar.x = foo.y) as baz

The easiest fix usually is to alias things accordingly:

select ...
from foo, (select ... from bar, foo as foo2 where bar.x = foo2.y and ...) as baz

See this question here for another example:

SQL subquery questions, "ERROR: invalid reference to FROM-clause entry ..."


In your case, this:

FROM 
    jobs, to_tsquery('english', 'coffeescript|backbone.js|javascript|node.js') AS query 
WHERE 
    (tsv @@ query AND enabled = true) 

Should be:

FROM 
    jobs
WHERE 
    (tsv @@ to_tsquery('english', 'coffeescript|backbone.js|javascript|node.js') AND enabled = true)

This should work too:

FROM 
    ( select to_tsquery('english', 'coffeescript|backbone.js|javascript|node.js') AS query ) q,
    jobs 
WHERE 
    (tsv @@ q.query AND enabled = true) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM