在
"EndpointId"
每一个
"Uid"
在里面
"Tags"
以及
"Type"
在里面
"Sensors"
将是:
db.collection.aggregate([
{ "$unwind": "$Tags" },
{ "$unwind": "$Tags.Sensors" },
{ "$group": {
"_id": {
"EndpointId": "$EndpointId",
"Uid": "$Tags.Uid",
"Type": "$Tags.Sensors.Type"
},
}},
{ "$group": {
"_id": {
"EndpointId": "$_id.EndpointId",
"Uid": "$_id.Uid",
},
"count": { "$sum": 1 }
}},
{ "$group": {
"_id": "$_id.EndpointId",
"tagCount": { "$sum": 1 },
"sensorCount": { "$sum": "$count" }
}}
])
或者对C
var results = collection.AsQueryable()
.SelectMany(p => p.Tags, (p, tag) => new
{
EndpointId = p.EndpointId,
Uid = tag.Uid,
Sensors = tag.Sensors
}
)
.SelectMany(p => p.Sensors, (p, sensor) => new
{
EndpointId = p.EndpointId,
Uid = p.Uid,
Type = sensor.Type
}
)
.GroupBy(p => new { EndpointId = p.EndpointId, Uid = p.Uid, Type = p.Type })
.GroupBy(p => new { EndpointId = p.Key.EndpointId, Uid = p.Key.Uid },
(k, s) => new { Key = k, count = s.Count() }
)
.GroupBy(p => p.Key.EndpointId,
(k, s) => new
{
EndpointId = k,
tagCount = s.Count(),
sensorCount = s.Sum(x => x.count)
}
);
哪些输出:
{
"EndpointId" : "89799bcc-e86f-4c8a-b340-8b5ed53caf83",
"tagCount" : 4,
"sensorCount" : 16
}
尽管考虑到所呈现的文档对于
“UID”
无论如何
$reduce
文件中的金额:
db.collection.aggregate([
{ "$group": {
"_id": "$EndpointId",
"tags": {
"$sum": {
"$size": { "$setUnion": ["$Tags.Uid",[]] }
}
},
"sensors": {
"$sum": {
"$sum": {
"$map": {
"input": { "$setUnion": ["$Tags.Uid",[]] },
"as": "tag",
"in": {
"$size": {
"$reduce": {
"input": {
"$filter": {
"input": {
"$map": {
"input": "$Tags",
"in": {
"Uid": "$$this.Uid",
"Type": "$$this.Sensors.Type"
}
}
},
"cond": { "$eq": [ "$$this.Uid", "$$tag" ] }
}
},
"initialValue": [],
"in": { "$setUnion": [ "$$value", "$$this.Type" ] }
}
}
}
}
}
}
}
}}
])
但是,该语句并不能很好地映射到linq,因此需要使用
BsonDocument
接口为语句生成bson。当然,同样的
“UID”
值“did”实际上出现在集合中的多个文档中,然后
$unwind
语句是必要的,以便从数组项中跨文档将这些语句“组合”在一起。
原件
你可以通过获取
$size
数组的。对于外部数组,这只是应用于文档中数组的字段路径,对于需要处理的内部数组项
$map
为了处理每一个
“标签”
元素,然后获取
美元大小
属于
“传感器”
和
$sum
要减少到总计数的结果数组。
每份文件应:
db.collection.aggregate([
{ "$project": {
"tags": { "$size": "$Tags" },
"sensors": {
"$sum": {
"$map": {
"input": "$Tags",
"in": { "$size": "$$this.Sensors" }
}
}
}
}}
])
在C代码中分配给类的位置如下:
collection.AsQueryable()
.Select(p => new
{
tags = p.Tags.Count(),
sensors = p.Tags.Select(x => x.Sensors.Count()).Sum()
}
);
如果他们回来了:
{ "tags" : 3, "sensors" : 13 }
{ "tags" : 2, "sensors" : 8 }
你想去哪里
$group
结果,例如在整个集合中,您将执行以下操作:
db.collection.aggregate([
/* The shell would use $match for "query" conditions */
//{ "$match": { "EndpointId": "89799bcc-e86f-4c8a-b340-8b5ed53caf83" } },
{ "$group": {
"_id": null,
"tags": { "$sum": { "$size": "$Tags" } },
"sensors": {
"$sum": {
"$sum": {
"$map": {
"input": "$Tags",
"in": { "$size": "$$this.Sensors" }
}
}
}
}
}}
])
对于您的C代码,如前所示:
collection.AsQueryable()
.GroupBy(p => "", (k,s) => new
{
tags = s.Sum(p => p.Tags.Count()),
sensors = s.Sum(p => p.Tags.Select(x => x.Sensors.Count()).Sum())
}
);
如果他们回来了:
{ "tags" : 5, "sensors" : 21 }
为了
"EndpointId
,则只需使用该字段作为分组键,而不是
null
或
0
当它被C驱动程序映射应用时:
collection.AsQueryable()
/* Use the Where if you want a query to match only those documents */
//.Where(p => p.EndpointId == "89799bcc-e86f-4c8a-b340-8b5ed53caf83")
.GroupBy(p => p.EndpointId, (k,s) => new
{
tags = s.Sum(p => p.Tags.Count()),
sensors = s.Sum(p => p.Tags.Select(x => x.Sensors.Count()).Sum())
}
);
当然,这是您提供给我们的两份文件样本的总和:
{“标签”:5,“传感器”:21}
所以这些都是非常简单的结果,一旦习惯了语法,就可以简单地执行管道。
我建议你熟悉一下
Aggregation Operators
从核心文档中,当然还有
"LINQ Cheat Sheet"
的表达式及其使用映射。
也见将军
LINQ Reference
在C驱动程序参考中,了解如何将其映射到MongoDB的聚合框架的其他示例。