0

几个小时后,我试图弄清楚如何使用一种必须在列表中的标准来创建标准。

如果我减少我的代码,我有以下两个域类:

酒店- 我要检索的基域类:

class Hotel {

    static hasMany = [rooms: Room, amenities: HotelAmenity]

}

HotelAmenity - 酒店有一系列设施。

class HotelAmenity {

    String name

}

#1我的第一种方法是这样的:

PagedResultList pgl = Hotel.createCriteria().list(max: limit, offset: offset) {
    // ..
    and {
        amenities {
            'in'("id",myLongIdsList)
    }
}

这行得通。但在这种情况下,我得到的每家酒店都至少包含一个指定的敌意。但我想要的目标是检索仅具有所有指定设施的酒店。

#2所以我尝试了以下

// ..
amenities {
    condition.hotelAmenities.collect { it.toLong() }.each {
        and {
            eq('id', it)
        }
}

但是这段代码看起来像是弄乱​​了结果集,因为如果定义了多个便利设施,它总是返回一个空列表。顺便说一句,在这种单一便利设施的情况下,我的结果列表中包含的所有酒店都不会在其便利设施列表中包含任何其他便利设施,而是我搜索的那个 - 即使其中很多都已分配。我完全不理解这种行为。

#3我尝试的另一种方法是使用listDistinct而不是list. 但是,一旦我认识到我没有得到一个返回PagedResultList的列表,我就没有再尝试这个了hotel domain objects。所以我不会有totalCount参数(我的分页功能需要它)

因此,我在编写自己的查询和/或使用 GORM 方法解决此问题之间陷入困境。也可能是我对这应该如何工作感到有些困惑。

对于任何通知或解决方案,我将非常高兴。

谢谢,克里斯托弗

PS:我使用 Grails 版本 1.3.7

PPS:如果缺少任何信息,请告诉我。

编辑

这是我现在提供的解决方案:

Map sqlParams = [:]
String mySql = "SELECT SQL_CALC_FOUND_ROWS hotel.id FROM hotel WHERE "
if(hotelAmenities.size()>0) {
  String commaSeperatedAmenities = hotelAmenities.toString()
  // the amenity IDs as comma seperates list so we can use them in the `IN` statement (ie 1,3,6,7)
  commaSeperatedAmenities = commaSeperatedAmenities.substring(1,commaSeperatedAmenities.length()-1)
  mySql += '( SELECT COUNT(hotel_amenities_id) from hotel_hotel_amenity ' +
           'WHERE hotel_amenities_id = hotel.id AND hotel_amenity_id IN ' +
           '(' + comaAmentities + ') ) = ' + condition.hotelAmenities.size()
}

mySql += 'LIMIT :offset, :limit'
sqlParams.put("offset",offset)
sqlParams.put("limit",limit)

def mresult = sqlInstance.rows(mySql,sqlParams)
List<Hotel> hotels = Hotel.getAll(mresult.collect {it.id})
int calcFoundRows = sqlInstance.rows("SELECT FOUND_ROWS()").get(0).get("FOUND_ROWS()").toString().toInteger()
4

2 回答 2

2

即时建立标准:

def neededAmenities = ...

PagedResultList pgl = Hotel.createCriteria().list(max: limit, offset: offset) {
    // ..
    amenities {
        and {
            neededAmenities.each { needed ->
                idEq (needed.id)
            }
        }
    }
}

在纯 SQL 中,这并不容易:

where exists(amenities.id == XXX) and exists(amenities.id == YYY) and (...) ... 

您可能会更优化地使用intersect具有如下语义的查询:

where intersect(
    select id from amenities where ..., 
    (:neededAmenities)) 
= (:neededAmenities)

这里有一些样本。

编辑:我试图构建第二类条件但失败了 -我看不到构建having count-type condition的方法。无论如何,它会比几个in-s 慢,因为它必须count Amenities对所有hotels.

于 2011-08-22T10:27:22.757 回答
0

更新,这应该会给你一个拥有所有设施的酒店列表,试试这个:

def amenitySize = HotelAmenity.list()?.size()
def hotelList = Hotel.createCriteria().list{
    sizeEq("amenities", amenitySize)
}
于 2011-08-22T17:14:12.740 回答