MongoDB -计数未读消息



我尝试为用户计数未读消息。

在我的模型中,我有一个属性,LastMessageDate,它包含在群聊天中最后创建的消息的日期。我也有一个Members属性(列表),其中包含在组聊天的成员。每个成员都有UserIdLastReadDate的性质。当用户在群聊中写入新消息或用户从群聊中加载消息时,LastReadDate更新。

现在我想计算一个特定用户有未读消息的聊天记录的数量(消息存储在另一个集合中)。我试试这个:

var db = GetGroupCollection();
var filter = Builders<ChatGroup>.Filter.Where(p => p.Members.Any(m => m.UserId == userId && m.LastReadDate < p.LastMessageDate));
return await db.CountDocumentsAsync(filter);

但是我收到以下错误:

LINQ表达式:{document}{Members}。((({文档}{UserId} = =730 ddbc7 - 5 d03 - 4060 b9ef - 2913 d0b1d7db)需要说明文档({}{LastReadDate} & lt;{document}{LastMessageDate})))有成员"p"这不能用来建立一个正确的MongoDB查询。

我该怎么办?有更好的解决方案吗?

根据评论中提供的数据,我认为需要聚合查询来实现结果。

  1. $set-设置Members字段

    1.1。$filter-使用Members数组作为input,过滤当前文档的UserIdLastMessageDate大于($gt)当前文档的LastReadDate的文档。

  2. $match- Filter document withMembers不是一个空数组。

db.groups.aggregate([
{
"$set": {
Members: {
$filter: {
input: "$Members",
cond: {
$and: [
{
$eq: [
"$$this.UserId",
1
]
},
{
$gt: [
"$LastMessageDate",
"$$this.LastReadDate"
]
}
]
}
}
}
}
},
{
$match: {
Members: {
$ne: []
}
}
}
])

Mongo Playground示例


对于c#语法,您可以直接将查询作为字符串提供,也可以将查询转换为BsonDocument语法。

注意,上面的查询将返回文档数组,因此您需要使用System。Linq对返回的文档进行计数。

using System.Linq;
var pipeline = new BsonDocument[]
{
new BsonDocument("$set", 
new BsonDocument("Members", 
new BsonDocument("$filter", 
new BsonDocument
{ 
{ "input", "$Members" },
{ "cond", new BsonDocument
(
"$and", new BsonArray
{
new BsonDocument("$eq", 
new BsonArray { "$$this.UserId", userId }),
new BsonDocument("$gt",
new BsonArray { "$LastMessageDate", "$$this.LastReadDate" })
}
)
}
}
)
)
),
new BsonDocument("$match",
new BsonDocument("Members",
new BsonDocument("$ne", new BsonArray())))
};
var db = GetGroupCollection();
return (await db.AggregateAsync<BsonDocument>(pipeline))
.ToList()
.Count;

当你想查询文档的一个嵌套列表,ElemMatch是你的解决方案,试着

var filter = builder.ElemMatch(o => o.Members,m => m.UserId == userId && m.LastReadDate < p.LastMessageDate);

最新更新