Grails标准:id不在hasMany列表中

时间:2014-08-20 21:41:42

标签: hibernate grails gorm criteria hibernate-criteria

我想查找当前用户的所有未查看消息。

可以让多个用户查看消息,因此使用布尔值来指示消息是否被查看将无效。所以一条消息有一个观察者列表。

简化的域类如下:

   class Message {
        static hasMany = [ viewees: User ]
        String content 
    }

    class User {
        String name
    }

要查找用户查看的消息很简单:

Message.withCriteria {
    viewees {
       idEq(currentUser.id)
    }
}

因此,要查找用户尚未查看过的消息,我认为我可以像这样添加not{ }

Message.withCriteria {
    viewees {
        not {
            idEq(currentUser.id)
        }
    }
}

但是这将返回所有具有不是当前用户的查看者的消息。这意味着它将返回另一个用户在查看者列表中的消息,无论当前用户是否在查看者列表中。

除此之外,如果有多个观看者,则返回同一消息的多个实例。

标准构建器还有inList

not { 
    inList( propertyName, list ) 
}

但我需要与此相反。类似的东西:

not { 
    inList( currentUser.id, 'viewees' ) 
}

但这并不支持。

我可以使用这样的东西吗?或者有不同的方式来解决这个问题?也许以某种方式改变领域模型?

2 个答案:

答案 0 :(得分:1)

您可以使用HQL来获取所需内容。像这样的简单查询:

class UserDomain {

    String name

    static List<MyMessage> findUnseenMessagesForUser(UserDomain user) {
        MyMessage.executeQuery(
                'select m from MyMessage m where :user not in elements(m.views)',
                [user: user]
        )
    }
}

/

void "test something"() {
        setup:
        def m1 = new MyMessage(content: "message 1")
        def m2 = new MyMessage(content: "message 2")
        def m3 = new MyMessage(content: "message 3").save(flush: true)

        def u1 = new UserDomain(name: "user1").save(flush: true)
        def u2 = new UserDomain(name: "user2").save(flush: true)
        def u3 = new UserDomain(name: "user3").save(flush: true)
        def u4 = new UserDomain(name: "user4").save(flush: true)


        when:
        m1.addToViews u1

        m2.addToViews u1
        m2.addToViews u3
        m2.addToViews u4

        m1.save(flush: true)
        m2.save(flush: true)



        then:
        UserDomain.findUnseenMessagesForUser (u2). containsAll ([m1, m2, m3])
        UserDomain.findUnseenMessagesForUser(u1).containsAll([m3])
    }

Here is an example and test case

答案 1 :(得分:0)

我建议通过创建一个额外的域类(如下所示)来显式建模读/未读信息:

class UserMessage {
    enum State = {READ, UNREAD}

    State state = State.UNREAD

    Message message
    User user
}

如果User收到新消息,则会将其添加到UserMessages为未读,当User读取消息时,您将状态更改为READ。您现在可以轻松检查单个用户收到的消息的状态。

这样做的好处是您不会向Message添加用户特定信息。我不会考虑跟踪谁将消息视为消息的责任(当然,这取决于您的业务领域中Message的含义)。

如果您有更多与消息相关的用户特定信息,例如已删除的标记(不再为此用户显示)或带有星号标记(我想保留),此额外课程也很有用它)。