如何在嵌套mongo数组中只检查前1

  • 本文关键字:数组 嵌套 mongo c# mongodb
  • 更新时间 :
  • 英文 :


目前我的通知文档有一个事件属性,这是一个事件数组。每个事件都有一个状态和一个日期。查询通知时,需要检查top状态是否为opened.

最近事件状态打开的有效对象-

{
"subject" : "Hello there",
"events" : [
{
"status" : "opened",
"date" : 2020-01-02 17:35:31.229Z 
},
{
"status" : "clicked",
"date" : 2020-01-01 17:35:31.229Z 
},
]
}

状态不是最近的

{
"subject" : "Hello there",
"events" : [
{
"status" : "opened",
"date" : 2020-01-01 17:35:31.229Z 
},
{
"status" : "clicked",
"date" : 2020-01-02 17:35:31.229Z 
},
]
}

目前我有查询,可以检查是否有任何事件的状态打开,但我不确定如何查询仅前1和按嵌套查询的日期排序。如有任何帮助,我将不胜感激。

var filter = Builders<Notification>.Filter.Empty;
filter &= Builders<Notification>.Filter.Regex("events.event", new BsonRegularExpression(searchString, "i"));
var results = await collection.FindSync(filter, findOptions).ToListAsync();

为了只获得最新的事件,您可以使用$reduce迭代事件并将每个事件与临时最新的事件进行比较:

db.collection.aggregate([
{
$addFields: {
latestEvent: {
$reduce: {
input: "$events",
initialValue: {status: null, date: 0},
in: {
$mergeObjects: [
"$$value",
{
$cond: [
{
$gt: [{$toDate: "$$this.date"}, {$toDate: "$$this.value"}]
},
"$$this",
"$$value"
]
}
]
}
}
}
}
}
])

看看它在操场的例子中是如何工作的

对于多个文档,结果只返回正确的文档示例

db.collection.aggregate([{
$addFields: {
lastevent: {
$filter: {
input: '$events',
as: 'element',
cond: {$eq: ['$$element.date',{$max: '$events.date'}]}
}
}
}
}, {
$match: {
'lastevent.status': 'opened'
}
}])

我是一个不喜欢用斧头的人,即使它是一个好斧头。

所以我认为事件无序是一件罕见的事情,所以我们不需要花费大量的资源来预先清除这些事件,因为它们会很少。

所以我的看法是获得所有打开的,并使用简单的。net迭代删除少数可能的,留下一个漂亮的,有序的,易于维护的方法。

public List<Notification> GetValidSubjectStatusList(IMongoCollection<Notification> mongoCollection){

var builder = Builders<Notification>.Filter;
var filter = builder.Eq(x => x.Events.FirstOrDefault().Status, "opened");
var listOf = mongoCollection.Find(filter).ToList();
var reducedList = new List<Notification>();
foreach(var hit in listOf){
if(hit.Events.Any() 
&& hit.Events.First()
.Date.Equals(hit.Events
.OrderByDescending(x => x.Date)
.FirstOrDefault()
))
{
reducedList.Add(hit);
}
}
return reducedList;
}

最新更新