基于ASP.Net Core 2.0 Web API统计MongoDB标签与传感器数量
Hey there! Let's figure out how to get those total tag and sensor counts from your MongoDB collection using ASP.NET Core 2.0 Web API. I'll break this down into practical, actionable steps for you.
First off, using MongoDB's aggregation framework is the most efficient way to do this—you avoid pulling all your data into the application layer, which is crucial if your collection grows large.
Aggregation Query (Direct MongoDB Shell)
If you want to test this directly in the MongoDB shell, here's a pipeline that calculates unique tag counts and total sensor counts (summing all sensors across all tags):
db.yourCollection.aggregate([ // Unwind the Tags array to treat each tag as a separate document { $unwind: "$Tags" }, // Group to calculate totals { $group: { _id: null, // Use $addToSet to collect unique tag UIDs, then we'll get its size uniqueTagIds: { $addToSet: "$Tags.Uid" }, // Sum the size of each tag's sensor array to get total sensors totalSensors: { $sum: { $size: "$Tags.Sensors" } } } }, // Convert the unique tag array to a count, and exclude the _id field { $project: { _id: 0, totalTags: { $size: "$uniqueTagIds" }, totalSensors: 1 } } ])
If you don't care about unique tags (just want to count every tag occurrence, even duplicates), replace the uniqueTagIds line with totalTags: { $sum: 1 } in the $group stage.
Now let's translate this into code for your Web API. First, make sure you have the MongoDB.Driver NuGet package installed (for .NET Core 2.0, use version 2.7.3 which is compatible):
Install-Package MongoDB.Driver -Version 2.7.3
Step 1: Define Model Classes
Map your MongoDB document structure to C# classes:
using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; using System.Collections.Generic; public class EndpointDocument { [BsonId] public ObjectId Id { get; set; } public string EndpointId { get; set; } public DateTime DateTime { get; set; } public string Url { get; set; } public List<Tag> Tags { get; set; } } public class Tag { public string Uid { get; set; } public List<Sensor> Sensors { get; set; } } public class Sensor { public string Uid { get; set; } // Add any other sensor properties you have } // DTO to return the count results public class CountResponse { public int TotalTags { get; set; } public int TotalSensors { get; set; } }
Step 2: Controller with Aggregation Logic
Here's how to implement the aggregation in your API controller:
using Microsoft.AspNetCore.Mvc; using MongoDB.Driver; using System.Threading.Tasks; [Route("api/[controller]")] [ApiController] public class StatsController : ControllerBase { private readonly IMongoCollection<EndpointDocument> _endpointCollection; // Inject MongoClient via dependency injection (register it in Startup.cs first!) public StatsController(IMongoClient mongoClient) { var database = mongoClient.GetDatabase("YourDatabaseName"); _endpointCollection = database.GetCollection<EndpointDocument>("YourCollectionName"); } [HttpGet("tag-sensor-counts")] public async Task<ActionResult<CountResponse>> GetTagAndSensorCounts() { // Build the aggregation pipeline var pipeline = new BsonDocument[] { new BsonDocument("$unwind", "$Tags"), new BsonDocument("$group", new BsonDocument { { "_id", BsonNull.Value }, { "uniqueTagIds", new BsonDocument("$addToSet", "$Tags.Uid") }, { "totalSensors", new BsonDocument("$sum", new BsonDocument("$size", "$Tags.Sensors")) } }), new BsonDocument("$project", new BsonDocument { { "_id", 0 }, { "TotalTags", new BsonDocument("$size", "$uniqueTagIds") }, { "TotalSensors", "$totalSensors" } }) }; // Execute the aggregation and get the result var countResult = await _endpointCollection.Aggregate<CountResponse>(pipeline).FirstOrDefaultAsync(); // Handle empty collection case return countResult ?? new CountResponse { TotalTags = 0, TotalSensors = 0 }; } }
Alternative: In-Memory Counting (Small Datasets Only)
If your collection is small and you prefer simpler code, you can fetch all documents and count in memory:
[HttpGet("tag-sensor-counts-in-memory")] public async Task<ActionResult<CountResponse>> GetCountsInMemory() { var allEndpoints = await _endpointCollection.Find(_ => true).ToListAsync(); // Count unique tags var uniqueTags = allEndpoints .SelectMany(endpoint => endpoint.Tags) .Select(tag => tag.Uid) .Distinct() .Count(); // Sum all sensors across all tags var totalSensors = allEndpoints .SelectMany(endpoint => endpoint.Tags) .Sum(tag => tag.Sensors?.Count ?? 0); return new CountResponse { TotalTags = uniqueTags, TotalSensors = totalSensors }; }
Quick Setup Note
Don't forget to register the IMongoClient in your Startup.cs ConfigureServices method:
services.AddSingleton<IMongoClient>(sp => new MongoClient("your-mongodb-connection-string"));
内容的提问来源于stack exchange,提问作者Mohammad Taherian

