2010-02-24 19 views
15

Tengo hotel entidad:Grails criterios de proyecciones - Obtener contar filas

class Hotel { 
City city 
} 

Ahora, necesito recuento de hoteles con determinada ciudad. Se podría hacer de esta manera:

def hotels = Hotel.findAllByCity(city) 
def cnt = hotels.size() 

Pero es muy sucia manera. Parece que a los criterios que sería mejor, pero no tengo ni idea de cómo ponerlo en práctica ...

Respuesta

23

Hay contadores dinámicos, así como buscadores de objetos de dominio:

Hotel.countByCity(city) 

Más detalles en el user guide , por supuesto,

44

Dave is right que puede utilizar los métodos countBy* para el conteo simple. Si necesita más de dos criterios, deberá volver al criteria api, HQL o SQL. Es muy común que necesite más de dos criterios, especialmente con una base de código activa y en evolución.

Aquí es un ejemplo de cómo se usaría el Criteria api hacer projections:

def c = Hotel.createCriteria() 

def hotelCount = c.get { 
    projections { 
     count('id') 
    } 
    gt("stars", 2)   
    eq("city", city)    
    eq("deleted", false) 

} 

alternativa (más elegante) incluso se podría utilizar criterios # cuentan como la siguiente:

def c = Hotel.createCriteria() 

def hotelCount = c.count { 
    gt("stars", 2)   
    eq("city", city)    
    eq("deleted", false) 

} 

Justo para completar la razón:

class Hotel { 
    City city 
    Boolean deleted = false 
    Integer stars 
} 

class City { 
    String name 
} 

An integr prueba de ation (usando el build-test-data plugin)

import grails.test.* 

class HotelTests extends GrailsUnitTestCase { 

    void testCriteria() { 
     City city1 = City.build(name:'one') 
     assertNotNull(city1) 
     City city2 = City.build(name:'two') 
     assertNotNull(city1) 

     Hotel fiveStarHotel= Hotel.build(city:city1, deleted:false, stars:5) 
     assertNotNull(fiveStarHotel) 

     Hotel hotelInCity2 = Hotel.build(city:city2, deleted:false, stars:5) 
     assertNotNull(hotelInCity2) 

     Hotel deletedHotel = Hotel.build(city:city1, deleted:true, stars:5) 
     assertNotNull(deletedHotel) 

     Hotel threeStarHotel = Hotel.build(city:city1, deleted:false, stars:3) 
     assertNotNull(threeStarHotel) 

     Hotel oneStarHotel = Hotel.build(city:city1, deleted:false, stars:1) 
     assertNotNull(oneStarHotel) 

     def c = Hotel.createCriteria() 

     def hotelCount = c.get { 
      projections { 
       count('id') 
      } 
      gt("stars", 2)   
      eq("city", city1)   
      eq("deleted", false) 

     } 
     assertEquals(2, hotelCount) //should only find the 5 and 3 star hotel 

     def c2 = Hotel.createCriteria() 
     hotelCount = c2.count { 
      gt("stars", 2)   
      eq("city", city1)   
      eq("deleted", false) 

     } 
     assertEquals(2, hotelCount) //should only find the 5 and 3 star hotel 
    } 
} 
+0

solo por simplicidad, ¿cómo puedo poner los criterios en una línea? ¿Debo agregar punto y coma (;) para cada declaración? –

+0

Creo que puede hacer: Hotel.createCriteria(). Count {gt ("stars", 2); eq ("ciudad", ciudad); eq ("deleted", false)} pero aún no lo he probado. –

+0

probado y probado ... ¡está funcionando! ¡Gracias! –

Cuestiones relacionadas