Spring Boot实现MongoDB当日活跃用户统计并写入集合咨询
Got it, let's break down how to implement this step by step in Spring Boot. I'll walk you through each part so you can follow along easily.
1. First, Set Up Dependencies
Make sure you have Spring Data MongoDB added to your project. If you're using Maven, add this to your pom.xml:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
For Gradle users, add this to your build.gradle:
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
2. Create Entity Classes
We need two entities to map to your MongoDB collections:
a. ProfileSection (for "Profile Section" collection)
This maps to the collection where your user active data lives:
import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "Profile Section") // Explicitly set collection name with space public class ProfileSection { private String Last_Active; // Match the field name from your MongoDB collection // Getters and setters public String getLast_Active() { return Last_Active; } public void setLast_Active(String last_Active) { Last_Active = last_Active; } }
b. ActiveUsers (for storing stats)
This will hold the daily active user count we're going to save:
import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import java.time.LocalDate; @Document(collection = "ActiveUsers") public class ActiveUsers { @Id private String id; private LocalDate statsDate; private long activeUserCount; // Constructor, getters and setters public ActiveUsers(LocalDate statsDate, long activeUserCount) { this.statsDate = statsDate; this.activeUserCount = activeUserCount; } // Getters and setters public LocalDate getStatsDate() { return statsDate; } public void setStatsDate(LocalDate statsDate) { this.statsDate = statsDate; } public long getActiveUserCount() { return activeUserCount; } public void setActiveUserCount(long activeUserCount) { this.activeUserCount = activeUserCount; } }
3. Create Repository Interfaces
Spring Data MongoDB will handle the database operations for us, so we just define these interfaces:
import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.Query; // For Profile Section collection public interface ProfileSectionRepository extends MongoRepository<ProfileSection, String> { // Count documents where Last_Active matches the date regex long countByLast_ActiveRegex(String dateString); } // For ActiveUsers collection public interface ActiveUsersRepository extends MongoRepository<ActiveUsers, String> { // Optional: Add a method to find existing stats for the same date (to avoid duplicates) ActiveUsers findByStatsDate(LocalDate statsDate); }
4. Implement the Service Layer
This is where we'll put the core logic: calculate the daily active count and save it to the ActiveUsers collection:
import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.format.DateTimeFormatter; @Service public class ActiveUserService { private final ProfileSectionRepository profileSectionRepo; private final ActiveUsersRepository activeUsersRepo; // Constructor injection (preferred over @Autowired) public ActiveUserService(ProfileSectionRepository profileSectionRepo, ActiveUsersRepository activeUsersRepo) { this.profileSectionRepo = profileSectionRepo; this.activeUsersRepo = activeUsersRepo; } public long calculateAndSaveDailyActiveUsers() { // Step 1: Generate the date string matching your MongoDB script's format (yyyy-MM-dd) LocalDate today = LocalDate.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String dateString = today.format(formatter); // Step 2: Count active users (matches your original regex query) long activeCount = profileSectionRepo.countByLast_ActiveRegex(dateString); // Step 3: Save or update the stats in ActiveUsers collection ActiveUsers existingStats = activeUsersRepo.findByStatsDate(today); if (existingStats != null) { existingStats.setActiveUserCount(activeCount); activeUsersRepo.save(existingStats); } else { activeUsersRepo.save(new ActiveUsers(today, activeCount)); } return activeCount; } }
5. Create the Controller Endpoint
Finally, expose the @GetMapping endpoint for Postman to call:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ActiveUserController { private final ActiveUserService activeUserService; public ActiveUserController(ActiveUserService activeUserService) { this.activeUserService = activeUserService; } @GetMapping("/Activeusers") public String getDailyActiveUsers() { long count = activeUserService.calculateAndSaveDailyActiveUsers(); return "Today's active user count: " + count; // Or return a JSON object for better Postman compatibility: // return Map.of("statsDate", LocalDate.now(), "activeUserCount", count); } }
Quick Notes & Optimizations
- If
Last_Activeis a Date type: Instead of using regex (which can be slow on large datasets), use a range query for better performance. Replace the count method inProfileSectionRepositorywith:
Then adjust the service logic to calculate the start/end of the day instead of using regex.@Query("{'Last_Active': {$gte: ?0, $lt: ?1}}") long countByLast_ActiveBetween(LocalDateTime startOfDay, LocalDateTime startOfNextDay); - Avoid duplicate stats: The service checks for existing stats for today and updates them instead of creating a new entry each time.
- MongoDB configuration: Make sure your
application.propertieshas the correct MongoDB connection details:spring.data.mongodb.uri=mongodb://localhost:27017/your-database-name
内容的提问来源于stack exchange,提问作者Prasad Mayya M

