2

新しいGrails2.1.0アプリケーションでスケジューリング機能を作成しています。私はRubyonRailsプロジェクトから移行しているので、クエリ戦略の多くはRailsスタイルから派生しています。私は次のドメインクラスを持っています:

Schedule.groovy

class Schedule {

    // Number of minutes between available appointment slots
    int defaultAppointmentInterval
    Time officeOpenStart
    Time officeOpenEnd
    Time lunchStart
    Time lunchEnd

    static hasMany = [inventorySlots: InventorySlot]

    static constraints = {
       // long validation rules
    }

    def boolean isAvailableAt(Date dateTime) {
        def isAvailable = true
        if (inventorySlots.isEmpty()) {
            isAvailable = false
        } else if (inventorySlotsSurroundingTime(dateTime).isEmpty()) {
            isAvailable = false
        }
        isAvailable
    }

    def inventorySlotsSurroundingTime(Date dateTime) {
        InventorySlot.surroundingTime(dateTime) {
            and {
                inventorySlot.schedule = this
            }
        }
    }
}

InventorySlot.groovy

class InventorySlot {

    Date startTime

    static belongsTo = [schedule: Schedule]

    static constraints = {
        startTime nullable: false, blank: false
    }

    static mapping = {
        tablePerHierarchy true
        schedule lazy: false
    }

    static namedQueries = {}

    def static surroundingTime(Date time) {
        [UnboundedInventorySlot.surroundingTime(time), BoundedInventorySlot.surroundingTime(time)].flatten()
    }

    def endTime() {
        return ((BoundedInventorySlot) this).endTime?: (UnboundedInventorySlot (this)).endTime()
    }
}

UnboundedInventorySlot.groovy

class UnboundedInventorySlot extends InventorySlot {

    static namedQueries = {
    //        surroundingTime { time ->
    //            le 'startTime', time
    //            ge 'startTime', time - 1
    //        }
    }

    @Override
    def static surroundingTime(Date time) {
        findAllByStartTimeLessThanEqualsAndStartTimeGreaterThanEquals(time, time - 1)
    }

    def Date endTime() {
        def endTime

        // If the office closing is defined, use that, otherwise use tonight @ 23:59:59
        endTime = schedule?.officeOpenEnd?: new DateTime(startTime + 1).withTimeAtStartOfDay().plusSeconds(-1).toDate()

        return endTime
    }
}

BoundedInventorySlot.groovy

class BoundedInventorySlot extends InventorySlot {

    Date endTime

    static constraints = {
        endTime nullable: false, blank: false, validator: {val, obj ->
            if (val.date != obj.startTime.date) { return ["invalid.differentDate", val.date] }
        }
    }

    static namedQueries = {
    //        surroundingTime { time ->
    //            le 'startTime', time
    //            ge 'endTime', time
    //        }
    }

    @Override
    def static surroundingTime(Date time) {
        findAllByStartTimeLessThanEqualsAndEndTimeGreaterThanEquals(time, time)
    }


    @Override
    def Date endTime() {
        endTime
    }
}

私がやりたいのは、Schedule#isAvailableAt(Date)メソッドを次のように実装することです。

def boolean isAvailableAt(Date dateTime) {
    def isAvailable = true

    if (inventorySlots.isEmpty()) {
        isAvailable = false
    } else if (inventorySlots.surroundingTime(dateTime).isEmpty()) {
        isAvailable = false
    }

    isAvailable
}

inventorySlots.surroundingTime()呼び出しは基本的に、InventorySlot.surroundingTime()InventorySlotsのユニバースにクエリを実行する代わりに、スケジュールインスタンスに関連付けられたインスタンスのみを事前にフィルタリングします。これはRailsで非常に一般的ですが、Grailsで「連鎖クエリ」または「コレクションクエリ」を検索しても、適切なドキュメントが提供されないようです。助けてくれてありがとう。

4

3 に答える 3

4

私は頭のてっぺんから2つのアプローチを考えることができます:それはうまくいくでしょう:

より複雑な動的ファインダー:

InventorySlots.findAllByScheduleAndStartTimeLessThanEqualsAndEndTimeGreaterThanEquals(this, time, time -1)

名前付きクエリをチェーンしてから、自動配線されたファインダーのいずれかを使用して実際のクエリを実行できるため、名前付きクエリのコメントを解除すると、次のようになります。

static namedQueries = {
        surroundingTime { time ->
            le 'startTime', time
            ge 'startTime', time - 1
        }
}

あなたは単に呼び出すことができます:

InventorySlots.surroundingTime(time).findAllBySchedule(this)

条件ビルダー構文のファンでない場合は、Grails2のクエリの場所を調べることもできます。これらは基準クエリよりもタイプセーフであり、同じ方法で連鎖させることができます。

更新:残念ながら、私は名前付きクエリがポリモーフィズムでどのように機能するかについての内部の仕組みに精通しておらず、それが問題であるとあなたがコメントした理由だと思います。ただし、最悪の場合は、次のように親に対してクエリを作成できます。

surroundingTime { time ->
            or {
                and {
                    eq('class', BoundedInventorySlot.name)
                    le 'startTime', time
                    ge 'startTime', time
                }
                and {
                    eq('class', UnboundedInventorySlot.name)
                    le 'startTime', time
                    ge 'startTime', time - 1
                }
            }
        }

***更新:スプレッド演算子を活用してタスクを簡素化できますか?つまり、このコードを保持しますが、.flatten()を削除し、siroundingTimeを名前付きクエリまたはwhereクエリとして呼び出します。

def static surroundingTime(Date time) {
        [UnboundedInventorySlot.surroundingTime(time), BoundedInventorySlot.surroundingTime(time)]
    }

次に、次のように呼び出すことができます。 Schedule.surroundingTime(time)*.findAllBySchedule(this).flatten()

発信者が結果を組み合わせるために知る必要があるのは理想的ではありませんが、興味深いアプローチかもしれません。

于 2012-08-25T01:54:51.357 に答える
0

参考として:

Grailsのドキュメントでのクエリチェーン:http://grails.org/doc/latest/guide/GORM.html#querying

「クエリ構成」の部分を参照してください。

于 2014-09-03T14:06:41.990 に答える
0

これが最初の検索結果だったので、回答を追加しました。ドキュメントによると、where句は「分離基準」です。

例:

def query = Person.where {
     lastName == "Simpson"
}
def bartQuery = query.where {
     firstName == "Bart"
}
Person p = bartQuery.find()

クエリ構成の場所

于 2015-08-03T22:07:43.977 に答える