一般用固定对象,比如 User 都知道用 db.GetCollection<User>(xxx)
但是在物联网中,不同的设备有不同的点位数据集,也就是不一样的列数据,列还需要支持动态增删处理 所以需要操作BsonDocument
这种数据结构,对一搬刚学习使用mongo的人还是略有点难度的,当然主要难度是在各种论坛、官网能够直接让你照抄的示例几乎没有。
1,动态查表、列历史数据-一次查总数+分页数据 pipeline
var pipeline = new BsonDocument[]
{
new BsonDocument("$match",new BsonDocument("$and", new BsonArray {
new BsonDocument("reportTime", new BsonDocument("$gte", startTime.ToUniversalTime())
.Add("$lte", endTime.ToUniversalTime())),
new BsonDocument($"{filedName}",new BsonDocument("$ne", BsonNull.Value))
})
),
new BsonDocument("$sort", new BsonDocument($"{MongoConstrants.MongoReportTime}", -1)),
new BsonDocument("$facet", new BsonDocument
{
{ "total",new BsonArray{new BsonDocument("$count", "total")
} } ,
{ "data",new BsonArray{new BsonDocument("$skip", pageNumber)
, new BsonDocument("$limit", pageSize),
new BsonDocument("$project", new BsonDocument()
.Add(filedName, $"${filedName}")
.Add(MongoConstrants.MongoReportTime, $"${MongoConstrants.MongoReportTime}")
)
} }
}
)
};
var collection = db.GetCollection<BsonDocument>($"{device.Code}");
var bsons = await collection.Aggregate<BsonDocument>(pipeline).ToListAsync();
2、各种聚合管道操作BsonDocument -取first last 数据
var pipeline = new BsonDocument[]
{
new BsonDocument("$match",new BsonDocument("$and", new BsonArray {
new BsonDocument("reportTime", new BsonDocument("$gte", startTime.ToUniversalTime())
.Add("$lte", endTime.ToUniversalTime())),
new BsonDocument($"{filedName}",new BsonDocument("$ne",BsonNull.Value))
})
),
new BsonDocument("$group", new BsonDocument
{
{ "_id",1},
{ $"firstval", new BsonDocument("$first", $"${filedName}") },
{ $"lastval", new BsonDocument("$last", $"${filedName}") },
{ $"firsttime", new BsonDocument("$first", $"${MongoConstrants.MongoReportTime}") },
{ $"lasttime", new BsonDocument("$last", $"${MongoConstrants.MongoReportTime}") }
}
),
new BsonDocument("$sort", new BsonDocument($"{MongoConstrants.MongoReportTime}", 1)),
new BsonDocument("$limit", 1)
};
3、常见实际场景累计时长计算
先追加下一条数据的时间,然后计算时差
var pipeline = new BsonDocument[]
{
new BsonDocument("$match",new BsonDocument("$and", new BsonArray {
new BsonDocument("reportTime", new BsonDocument("$gte", startTime.ToUniversalTime())
.Add("$lte", endTime.ToUniversalTime()))
})),
new BsonDocument("$setWindowFields", new BsonDocument()
.Add("sortBy", new BsonDocument()
.Add("reportTime", -1)
)
.Add("output", new BsonDocument()
.Add("prev", new BsonDocument()
.Add("$first", "$reportTime")
.Add("window", new BsonDocument()
.Add("documents", new BsonArray()
.Add(-1.0)
.Add(0.0)
)
)
)
)),
new BsonDocument("$set", new BsonDocument()
.Add("_diffTime", new BsonDocument()
.Add("$subtract", new BsonArray()
.Add("$prev")
.Add("$reportTime")
)
)
.Add("prev", "$$REMOVE")),
new BsonDocument("$group", new BsonDocument
{
{ "_id", $"${filedName}" },
{ $"totalTime", new BsonDocument("$sum", $"$_diffTime") }
}),
};
4、一定时期内获取取指定数据量,分组的平均值
var pipeline = new BsonDocument[]
{
new BsonDocument("$match",new BsonDocument("$and", new BsonArray {
new BsonDocument("reportTime", new BsonDocument("$gte", startTime.ToUniversalTime())
.Add("$lte", endTime.ToUniversalTime())),
new BsonDocument($"{filedName}",new BsonDocument("$ne",BsonNull.Value))
} )),
// 投影出一个新的字段,其值为reportTime向下取整到最近的5分钟的时间戳
new BsonDocument("$addFields", new BsonDocument
{
{ "roundedTime", new BsonDocument("$toDate", new BsonDocument("$subtract", new BsonArray { "$reportTime", new BsonDocument("$mod", new BsonArray { new BsonDocument("$toLong", "$reportTime"), avgNum }) })) }
}),
// 按roundedTime字段进行分组,并计算value字段的平均值
new BsonDocument("$group", new BsonDocument
{
{ "_id", "$roundedTime" },
{ $"{filedName}", new BsonDocument("$avg", $"${filedName}") }
}),
// 按roundedTime字段排序结果
new BsonDocument("$sort", new BsonDocument("_id", 1))
};