Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

318
Visualizações
Use Rails 'contains operator' (o alternativa) para buscar con múltiples valores

Tengo dos modelos: Autor y Libro, donde

 class Book< ApplicationRecord belongs_to :author end class Author< ApplicationRecord has_many :books end

El autor tiene un nombre: cadena

El libro tiene title:string y author_id como índice

Estoy interesado en encontrar todos los autores que tienen libros que contienen algunas cadenas dadas

por ejemplo, si los términos son ['mago', 'cien', 'dos ciudades'] quiero devolver los autores cuyos libros contienen los términos en el título (un título de libro que contiene 'mago' Y un libro que contiene 'cien' Y...)

Podría ir con algo como

 class Post scope :including_all_title, -> (titles) { where(matching_tag_query(titles, 'AND')) } private def matching_tag_query(titles, condition_separator = 'AND') titles.map { |t| "(title LIKE '%#{t}%')" }.join(" #{condition_separator} ") end end

( Author.joins(:books).merge(Books.inclusive_all_title... ) pero no parece muy bueno a medida que aumenta el número de términos.

He visto respuestas que contienen '@>' de Postgres (por ejemplo, Postgres: ¿verificar si el campo de matriz contiene valor? )

pero hasta ahora no pude hacerlo funcionar (probablemente la sintaxis no sea buena, no obtengo un error pero no resultados)

Me pregunto cómo podría lograr eso con Active Record (u otra solución mejor que la mía)

Editar : me doy cuenta de que podría no haber sido claro, lo que estoy tratando de hacer es: Si Author(name:'John') tiene libros Book(title: 'The wonderful Wizard of Oz') Book(title: 'Fantastic beasts') Book(title: 'Some other work') Book(title: 'Another book') y consulto por ["%wizard%", "%fantastic%"] Me gustaría encontrar el autor cuyos libros, coincida con TODOS las palabras clave, por lo que en este caso, John sería una coincidencia (porque "mago" coincide con un libro y "fantástico" coincide con otro, incluso si algunos no coinciden, estoy interesado en mis palabras clave)

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Esto debería funcionar:

 def matching_tag_query(titles, condition_separator = 'AND') titles.map { |t| "(title LIKE '%#{t}%')" }.join(" #{condition_separator} ") end

pero está sujeto a la inyección de SQL y puede hacerlo más limpio usando expr op any(array) y expr op all(array) de PostgreSQL con el operador ILIKE. Algo más como esto:

 scope :including_all_title, -> (titles) { where('title ilike all(array[?])', titles.map { |t| "%#{sanitize_sql_like(t)}%" }) scope :including_any_title, -> (titles) { where('title ilike any(array[?])', titles.map { |t| "%#{sanitize_sql_like(t)}%" })

Debería estar bien para titles realistas, pero si alguien le arroja un par de miles de titles , entonces podría encontrarse con límites de tamaño de consulta y no encontraría nada de todos modos.


En respuesta a los comentarios: si desea encontrar todos los libros que coincidan con alguna de las palabras clave, entonces:

 books = Book.where('title like any(array[?])', titles.map { |t| "%#{sanitize_sql_likt(t)}%" })

Luego para encontrar los autores:

 Author.where(id: books.select(:author_id))

Eso hará una subconsulta como esta:

 select * from authors where id in (select author_id from books where ...)

que no será tan eficiente como podría ser, pero debería ser lo suficientemente bueno. Si es demasiado lento, conviértalo en JOIN.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda