0

次を返す HQL クエリを作成しようとしています。

彼らの propertyTags が my includeTags に含まれている、
または my propertyTags がその includeTags に含まれており、
かつ彼らの propertyTags が my excludeTags に含まれておらず、
かつ my propertyTags がそれらの excludeTags に含まれていない。

ここに私がこれまでに持っているものがあります:

def thePropertyTags = this.propertyTags
if(thePropertyTags == null || thePropertyTags.size() == 0) {
    thePropertyTags = [ Tag.UNUSED_TAG ]
}

def theInclusions = this.inclusionTags
if(theInclusions == null || theInclusions.size() == 0) {
    theInclusions = [ Tag.UNUSED_TAG ]
}

def theExclusions = this.exclusionTags
if(theExclusions == null || theExclusions.size() == 0) {
    theExclusions = [ Tag.UNUSED_TAG ]
}

List<MyDomain> objects = MyDomain.executeQuery("""
    SELECT DISTINCT o
    FROM MyDomain o

    JOIN o.propertyTags as propertyTags
    JOIN o.exclusionTags as exclusions
    JOIN o.inclusionTags as inclusions

    WHERE o.id != :id
    AND o.isActive = true

    AND (
        exclusions IS NULL
        OR exclusions IS EMPTY
        OR exclusions NOT in (:propertyTags)
    )

    AND propertyTags NOT in (:exclusions)

    AND (
        inclusions in (:propertyTags)
        OR propertyTags in (:inclusions)
    )

""", [id: id, inclusions: theInclusions, exclusions: theExclusions, propertyTags: thePropertyTags])

問題は、包含/プロパティタグの一致に関係なく、除外タグを結合すると何も返されないことです。すべての除外句を削除しても何も返されません。何かを返す唯一の方法は、JOIN を完全に削除することです。

ドメイン:

MyDomain {
    boolean isActive = true

    static hasMany = [propertyTags: Tag, inclusionTags: Tag, exclusionTags: Tag]

    static constraints = {
        propertyTags(nullable: false)
        inclusionTags(nullable: false)
        exclusionTags(nullable: false)
    }
}

Tag {
    private static final List<Integer> TAG_TYPES = [...]

    String name
    int type
    String description

    static constraints = {
        name(unique: true, nullable: false, blank: false)
        type(inList: [TAG_TYPES])

        description(nullable: true, blank: true)
    }
}

アップデート:

包含/除外を次のLEFT JOINように変更しましたが、除外がクエリに含まれている場合、返されるレコードはまだありません:

List<MyDomain> objects = MyDomain.executeQuery("""
    SELECT DISTINCT o
    FROM MyDomain o

    JOIN o.propertyTags as propertyTags
    LEFT JOIN o.exclusionTags as exclusions
    LEFT JOIN o.inclusionTags as inclusions

    WHERE o.id != :id
    AND o.isActive = true

    AND exclusions NOT in (:propertyTags)
    AND propertyTags NOT in (:exclusions)

    AND (
        inclusions in (:propertyTags)
        OR propertyTags in (:inclusions)
    )

""", [id: id, inclusions: theInclusions, exclusions: theExclusions, propertyTags: thePropertyTags])
4

1 に答える 1

0

最初の問題は、除外タグで内部結合を行っていることです。これにより、除外タグを持つレコードのみが返されるようになります。また、包含タグのない「MyDomain」で「Their propertyTags are in my includeTags」を満たすこともできるので、それにも参加したままにする必要があります

これを試して

LEFT JOIN o.exclusionTags as exclusions
LEFT JOIN o.inclusionTags as inclusions

次に、これを簡単に実行できるはずです。

AND (
    exclusions NOT in (:propertyTags)
)

編集:わかりました-問題はありません.Hibernateはこれについて奇妙です。元の回答を投稿する前に、すべてのタグが nullable false であることを認識していなかったため、左結合を行う意味がありません。

MyDomain.executeQuery("select distinct m from MyDomain m join m.propertyTags as pt join m.inclusionTags as it where m.id != :id and m.isActive = true and (pt in (:inclusionTags) or it in (:propertyTags)) and m not in (select m from MyDomain m join m.propertyTags as pt where pt in (:exclusionTags)) and m not in (select m from MyDomain m join m.exclusionTags as et where et in (:propertyTags))", [id: id, inclusionTags: theInclusions, propertyTags: thePropertyTags, exclusionTags: theExclusions])
于 2013-10-29T02:12:50.757 に答える