Truy vấn để đếm số lần xuất hiện "duy nhất" trong "EndpointId"
của mỗi "Uid"
trong "Tags"
và "Type"
trong "Sensors"
sẽ là:
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" }
}}
])
Hoặc cho 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)
}
);
Kết quả đầu ra:
{
"EndpointId" : "89799bcc-e86f-4c8a-b340-8b5ed53caf83",
"tagCount" : 4,
"sensorCount" : 16
}
Mặc dù thực sự là cách "hiệu quả nhất" để làm điều này xét rằng các tài liệu được trình bày có các giá trị duy nhất cho "Uid"
dù sao cũng sẽ là $reduce
số tiền trong chính các tài liệu:
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" ] }
}
}
}
}
}
}
}
}}
])
Tuy nhiên, câu lệnh không thực sự liên kết tốt với LINQ, vì vậy bạn sẽ được yêu cầu sử dụng BsonDocument
giao diện để xây dựng BSON cho câu lệnh. Và tất nhiên nơi "Uid"
giống nhau các giá trị "did" trên thực tế xảy ra trong nhiều tài liệu trong bộ sưu tập, sau đó là $unwind
các câu lệnh là cần thiết để "nhóm" các câu lệnh đó lại với nhau trên các tài liệu từ bên trong các mục nhập mảng.
Bản gốc
Bạn giải quyết vấn đề này bằng cách lấy $size
của các mảng. Đối với mảng bên ngoài, điều này chỉ áp dụng cho đường dẫn trường của mảng trong tài liệu và đối với các mục mảng bên trong, bạn cần xử lý với $map
để xử lý từng "Tags"
rồi lấy phần tử $size
của "Sensors"
và $sum
mảng kết quả để giảm xuống tổng số.
Mỗi tài liệu sẽ là:
db.collection.aggregate([
{ "$project": {
"tags": { "$size": "$Tags" },
"sensors": {
"$sum": {
"$map": {
"input": "$Tags",
"in": { "$size": "$$this.Sensors" }
}
}
}
}}
])
Nơi bạn đã gán cho các lớp trong mã C # của mình sẽ như thế nào:
collection.AsQueryable()
.Select(p => new
{
tags = p.Tags.Count(),
sensors = p.Tags.Select(x => x.Sensors.Count()).Sum()
}
);
Nơi những thứ đó trở về:
{ "tags" : 3, "sensors" : 13 }
{ "tags" : 2, "sensors" : 8 }
Nơi bạn muốn $group
kết quả, chẳng hạn như trên toàn bộ bộ sưu tập, thì bạn sẽ thực hiện:
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" }
}
}
}
}
}}
])
Mã C # của bạn giống như trước đây sẽ là:
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())
}
);
Nơi những thứ đó trở về:
{ "tags" : 5, "sensors" : 21 }
Và cho "EndpointId
, thì bạn chỉ cần sử dụng trường đó làm khóa nhóm, thay vì null
hoặc 0
vì nó được áp dụng bởi ánh xạ trình điều khiển 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())
}
);
Tất nhiên, tổng số của hai mẫu tài liệu bạn đã cung cấp cho chúng tôi bằng nhau:
{ "tags" : 5, "sensors" : 21 }
Vì vậy, đây là những kết quả rất đơn giản, với việc thực thi đường dẫn đơn giản khi bạn đã quen với cú pháp.
Tôi khuyên bạn nên tự làm quen với Toán tử tổng hợp từ tài liệu cốt lõi và tất nhiên là "LINKTrang tính gian lận " các biểu thức và ánh xạ sử dụng của chúng từ kho lưu trữ mã Trình điều khiển C #.
Cũng xem Tham chiếu LINQ chung trong tài liệu tham khảo Trình điều khiển C # để biết các ví dụ khác về cách thức này ánh xạ vào Khung tổng hợp của MongoDB nói chung.