0

数時間以来、私は一種の必須リスト基準で基準を作成する方法を理解しようとしています。

コードを減らすと、次の 2 つのドメイン クラスがあります。

ホテル- 取得するベース ドメイン クラス:

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)
    }
}

これは機能します。しかし、この場合、指定された anem の少なくとも 1 つを含むすべてのホテルが返されます。しかし、私が望む目標は、指定されたすべてのアメニティのみを備えたホテルを検索することです。

#2だから私は次のことを試しました

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

しかし、このコードは結果セットを台無しにしているように見えます。定義されたアメニティが複数ある場合、常に空のリストを返すためです。ちなみに、この 1 つのアメニティのシナリオでは、結果リストに含まれるすべてのホテルのアメニティ リストには、私が検索したもの以外のアメニティはありません。私はこの行動をまったく理解していません。

#3私が試したもう 1 つのアプローチは、listDistinctの代わりにをいじることでしlistた。PagedResultListしかし、返されたリストが返されないことに気付いたので、これ以上試しませんでしたhotel domain objectstotalCountそのため、パラメーターはありません(ページネーション機能に必要です)。

そのため、独自のクエリを作成するか、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)

ここにいくつかのサンプルがあります。

編集:私は2番目のタイプの基準を構築しようとしましたが失敗しました-タイプの条件を構築する方法がわかりませんhaving count。とにかく、それはすべてのためにそうしinなければならないので、それはいくつかの-sより遅くなるでしょう。count Amenitieshotels

于 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 に答える