我尝试为用户计数未读消息。
在我的模型中,我有一个属性,LastMessageDate
,它包含在群聊天中最后创建的消息的日期。我也有一个Members
属性(列表),其中包含在组聊天的成员。每个成员都有UserId
和LastReadDate
的性质。当用户在群聊中写入新消息或用户从群聊中加载消息时,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查询。
我该怎么办?有更好的解决方案吗?
根据评论中提供的数据,我认为需要聚合查询来实现结果。
-
$set
-设置Members
字段1.1。
$filter
-使用Members
数组作为input
,过滤当前文档的UserId
和LastMessageDate
大于($gt
)当前文档的LastReadDate
的文档。 -
$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);