Grails标准:id不在hasMany列表中



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

消息可以供多个用户查看,因此使用布尔值来指示是否查看消息将不起作用。因此,消息有一个视图列表。

简化的域类如下:

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

但是不支持。

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

您可以使用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])
    }

下面是一个示例和测试用例

我建议通过创建一个额外的域类(类似于这样)来显式地建模已读/未读信息:

class UserMessage {
    enum State = {READ, UNREAD}
    State state = State.UNREAD
    Message message
    User user
}

如果User接收到一个新的消息,它被添加到UserMessages为未读,当User读取消息时,您将状态更改为READ。您现在可以很容易地检查单个用户收到的消息的状态。

这样做的好处是不需要向Message添加特定于用户的信息。我不认为跟踪谁看到了消息是消息的责任(当然,这取决于Message在您的业务领域中的含义)。

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

最新更新