我想查找当前用户的所有未查看消息。
可以让多个用户查看消息,因此使用布尔值来指示消息是否被查看将无效。所以一条消息有一个观察者列表。
简化的域类如下:
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' )
}
但这并不支持。
我可以使用这样的东西吗?或者有不同的方式来解决这个问题?也许以某种方式改变领域模型?
答案 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])
}
答案 1 :(得分:0)
我建议通过创建一个额外的域类(如下所示)来显式建模读/未读信息:
class UserMessage {
enum State = {READ, UNREAD}
State state = State.UNREAD
Message message
User user
}
如果User
收到新消息,则会将其添加到UserMessages
为未读,当User
读取消息时,您将状态更改为READ
。您现在可以轻松检查单个用户收到的消息的状态。
这样做的好处是您不会向Message
添加用户特定信息。我不会考虑跟踪谁将消息视为消息的责任(当然,这取决于您的业务领域中Message
的含义)。
如果您有更多与消息相关的用户特定信息,例如已删除的标记(不再为此用户显示)或带有星号标记(我想保留),此额外课程也很有用它)。