Pregunta

Estoy tratando de usar PG_Search para buscar a través de un modelo asociado. Cuando ejecuto una búsqueda, recibo el error "PG :: Error: Error: Columna Plans.Name no existe". Estoy ejecutando la búsqueda en el modelo "Planes" y tratando de buscar contra la asociación el "lugar" con una columna "Nombre". El modelo Has_Many: que conecta estos es polimórfico. De alguna manera, la consulta SQL está combinando los dos y lanzando un error. He ejecutado la migración Associated_Against (Rails G PG_Search: Migration: Associated_against), recorrí la documentación y busqué a otros con el error y no tengo nada, debe ser que solo estoy pasando por alto algo. Se ejecuta correctamente (sin los resultados de búsqueda más extensos) si solo elimino la línea Associated_Against en Plan.rb. ¡Cualquier ayuda sería apreciada!

Plan.RB:

class Plan < ActiveRecord::Base
    belongs_to :user
    has_many :plan_places, :dependent => :destroy
    has_many :places, through: :plan_places, source: :plan

    include PgSearch
    pg_search_scope :search, :against => [:title, :summary],
        associated_against: { places: [:name, :address]},
        using: {tsearch: {dictionary: "english"}},
        ignoring: :accents

    def self.text_query(query)
        if query.present?
          search(query)
        else
          scoped
        end
    end
end

Lugar.rb:

class Place < ActiveRecord::Base
    has_many :plan_places, as: :sortable #polymorphic -- could this be the issue??
    has_many :plans, through: :plan_places

   include PgSearch
        multisearchable :against => [:name, :address]
        pg_search_scope :search, against: [:name, :address],
            using: {tsearch: {dictionary: "english"}},
            ignoring: :accents
    def self.text_query(query)
            if query.present?
              search(query)
            else
              scoped
            end
    end
end

Controlador:

def index
    query = params[:query]
    @plans = Plan.text_query(query)
  end

Mensaje de error completo:

PG::Error: ERROR:  column plans.name does not exist
LINE 1: ...OUTER JOIN (SELECT "plans"."id" AS id, string_agg("plans"."n...
                                                             ^
: SELECT "plans".*, ((ts_rank((to_tsvector('english', unaccent(coalesce("plans"."title"::text, ''))) || to_tsvector('english', unaccent(coalesce("plans"."summary"::text, ''))) || to_tsvector('english', unaccent(coalesce(pg_search_ef8b0c36567cc241900c73.pg_search_1d546fcf34c118d2a7b8f6::text, ''))) || to_tsvector('english', unaccent(coalesce(pg_search_ef8b0c36567cc241900c73.pg_search_f3147101e01c522d780049::text, '')))), (to_tsquery('english', ''' ' || unaccent('giraffe') || ' ''')), 0))) AS pg_search_rank FROM "plans" LEFT OUTER JOIN (SELECT "plans"."id" AS id, string_agg("plans"."name"::text, ' ') AS pg_search_1d546fcf34c118d2a7b8f6, string_agg("plans"."address"::text, ' ') AS pg_search_f3147101e01c522d780049 FROM "plans" INNER JOIN "plan_places" ON "plan_places"."plan_id" = "plans"."id" INNER JOIN "plans" "places_plans" ON "places_plans"."id" = "plan_places"."plan_id" GROUP BY "plans"."id") pg_search_ef8b0c36567cc241900c73 ON pg_search_ef8b0c36567cc241900c73.id = "plans"."id" WHERE (((to_tsvector('english', unaccent(coalesce("plans"."title"::text, ''))) || to_tsvector('english', unaccent(coalesce("plans"."summary"::text, ''))) || to_tsvector('english', unaccent(coalesce(pg_search_ef8b0c36567cc241900c73.pg_search_1d546fcf34c118d2a7b8f6::text, ''))) || to_tsvector('english', unaccent(coalesce(pg_search_ef8b0c36567cc241900c73.pg_search_f3147101e01c522d780049::text, '')))) @@ (to_tsquery('english', ''' ' || unaccent('giraffe') || ' '''))))  ORDER BY pg_search_rank DESC, "plans"."id" ASC, created_at DESC
¿Fue útil?

Solución

Terminé usando una solución alternativa algo hacky si alguien más experimenta esto. En el método de búsqueda del modelo del plan, solo ejecuto la búsqueda en el modelo infantil (lugares), obtengo los planes asociados de los resultados utilizando el Has_Many: a través de la tabla (plan_places) y agrego esta lista a los resultados de búsqueda del plan regular. Es feo y probablemente muy ineficiente, así que si alguien conoce una respuesta "real", ¡envíe!

def self.text_query(query)
    if query.present?
      place_ids = Place.text_query(query).map(&:id).uniq
      plan_ids = PlanPlace.where(sortable_id: place_ids, sortable_type: "Place").map(&:plan_id).uniq
      plans = find(plan_ids)
      plans = plans + search(query)
    else
      scoped
    end
  end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top