几个小时以来,我试图弄清楚如何使用一种必须在列表中的条件来创建条件。
如果减少代码,则有以下两个域类:
酒店-我要检索的基本域类:
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()
最佳答案
动态建立标准:
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)
一些示例here。
编辑:我试图构造第二类条件,但失败了-I see no way to build
having count
-type condition。无论如何,它将比几个in
-s慢,因为所有count
都必须Amenities
hotels
。
关于list - 具有一对多关系的GORM createCriteria,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7144944/