¿Cuál es la manera más rápida y estándar de "masar búsqueda" un conjunto de nietos (has_many, has_many) pertenecientes a un solo objeto?

Caso de uso: en este sitio, los usuarios podrán continuar y seleccionar la propiedad de alquiler por una cantidad específica de días. Los usuarios a menudo estarán vendiendo el mismo tipo de propiedad de alquiler.

Problema: Debido a que múltiples "vendedores" se alquila el mismo artículo exacto, la "página de detalles de propiedad" se tienen muchos listados creados por muchos vendedores diferentes (o en algún caso, un vendedor tendrá múltiples propiedades disponibles cayendo en la misma "página de detalles de propiedad"). Cada uno de estos objetos de "listings" tienen muchos pricing objetos que contienen una fecha, un precio y una disponibilidad booleana.

Los modelos actuales se desglosan a continuación:

property.rb

has_many :listings
has_many :prices, :through => :listings

listado.rb

belongs_to :user
belongs_to :property
has_many :prices

precio.rb

belongs_to :listing

Lo que he intentado:

Si, por ejemplo, quisiera obtener la suma del MINIMUM de precios para una propiedad específica, había tropezado con esto:

# property.rb

# minimum price for a pricing set out of all of the price objects
def minimum_price(start_date, end_date)
     # this would sum up each days pricing to give the rental period a final price
     prices = self.prices.where("day <= ?", end_date).where("day >= ?", start_date).sum(:price)
end

Cuando lo hago así, sin embargo, simplemente combina cada uno de los precios de los usuarios dando nada de uso.

Cualquier ayuda sería muy apreciada! Por supuesto que podría bucle a través de una lista de propiedades hasta que encontré un precio mínimo fijado para un rango de fecha dado, pero eso parece que tomaría una cantidad innecesaria de tiempo y sería en gran medida ineficiente.

EDITUn ejemplo de datos que deben ser producidos es un conjunto de objetos de precio que son los más baratos en un rango de fecha específico de la lista de ONE en particular. No sólo puede combinar todas las fechas mejor precio de todos los usuarios y añadirlas como el comprador se alquilará de ONE vendedor.

Este es un ejemplo real de la salida deseada, ya que puede ver estos precios son TODOS del mismo ID de listado.

[#, #, #, #]

Pregunta hecha hace 3 años, 4 meses, 28 días - Por quantumcoder403a


3 Respuestas:

  • Así que parece que estás llamando a esto en una propiedad así que:

         prices = self.prices.where("prices.day >= ? AND prices.day <= ?", start_date, end_date).sum(:price).group_by {|price| price.listing_id}
    

    Probablemente hay una forma basada en SQL que puede utilizar relaciones AR para hacer esto. Pero esto le dará un hash con una clave para cada list_id y el valor de esa clave debe ser la suma. Yo digo "debería" porque esto es un poco abstracto para mí para hacer sin un sistema para probarlo.

    Respondida el Dec 17, 2020 a las 14:55 - por byteninja

    Votos positivos: 0 | Votos negativos: 0

  • Para obtener la suma del precio mínimo para una propiedad específica en un rango de fechas dado, podrías modificar el método minimum_price en el modelo Property de la siguiente manera:

    ruby
    

    property.rb

    minimum price for a pricing set out of all of the price objects

    def minimum_price(start_date, end_date) self.prices .where("day >= ?", start_date) .where("day <= ?", end_date) .group(:listing_id)

    Agrupa por listing_id para obtener el precio mínimo de cada listing

    .minimum(:price)

    Obtiene el precio mínimo de cada listing

    .values.sum

    Suma los precios mínimos

    end

    Con estos cambios, el método minimum_price obtendrá los precios mínimos de cada listing en el rango de fechas proporcionado y luego sumará estos precios mínimos para devolver la suma total del precio mínimo para la propiedad.

    Este enfoque optimiza la consulta SQL al agrupar y obtener solo los precios mínimos necesarios en lugar de recuperar todos los precios y procesarlos en Ruby, lo que debería proporcionar un mejor rendimiento y eficiencia en la búsqueda de los precios mínimos para una propiedad específica en un rango de fechas dado.

    Respondida el Dec 18, 2020 a las 14:53 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Para realizar una búsqueda más rápida y estándar de un conjunto de nietos (hasmany, hasmany) pertenecientes a un solo objeto, puedes utilizar la siguiente técnica:

    Paso 1: Utiliza la relación has_many through para obtener los objetos nietos

    ruby
    listings = property.listings
    

    Paso 2: Utiliza la relación has_many para obtener la colección de objetos de nieto

    ruby
    prices = listings.prices
    

    Paso 3: Utiliza las consultas del ámbito para filtrar la colección de nietos

    Para filtrar la colección de precios por un rango de fechas específico, puedes utilizar consultas de ámbito como where y between:

    ruby
    start_date = Date.new(2023, 1, 1)
    end_date = Date.new(2023, 1, 7)
    
    prices = prices.where(day: start_date..end_date)
    

    Paso 4: Agrupa los precios por el objeto padre (listing)

    Para agrupar los precios por el objeto listing, puedes utilizar el método group_by:

    ruby
    prices_by_listing = prices.group_by(&:listing)
    

    Paso 5: Encuentra el precio mínimo para cada grupo de precios

    Para encontrar el precio mínimo para cada grupo de precios, puedes utilizar el método min_by:

    ruby
    minimum_prices = prices_by_listing.map { |listing, prices| prices.min_by(&:price) }
    

    Resultado:

    minimum_prices contendrá una lista de objetos de precios, cada uno representando el precio mínimo para un rango de fechas específico de un listing en particular.

    Ejemplo de salida:

    ruby
    minimum_prices.each do |price|
      puts "Listing ID: {price.listing_id}, Minimum Price: #{price.price}"end
    

    Nota:

    Este enfoque es más eficiente que iterar a través de todas las propiedades y buscar el precio mínimo para cada rango de fechas. Utiliza consultas de ámbito y operaciones de agrupación para filtrar y agrupar los datos de manera eficiente.

    Respondida el Dec 18, 2020 a las 14:57 - por Gemini

    Votos positivos: 0 | Votos negativos: 0