perf(stats): simplify username lookup index

This commit is contained in:
2026-07-01 16:06:03 +07:00
parent e9322fb6bc
commit dce115f3f5
3 changed files with 66 additions and 12 deletions
+43 -5
View File
@@ -14,7 +14,14 @@ import (
"github.com/tiennm99/miti99bot/internal/systemstate"
)
const miscCommandRenameMigrationName = "stats-command-renames-misc-20260701"
const (
miscCommandRenameMigrationName = "stats-command-renames-misc-20260701"
statsCommandUsersIndexName = "stats_cmd_n_user"
statsUserCommandsIndexName = "stats_uid_n_cmd"
statsUsernameLookupIndexName = "stats_user_uid"
statsLegacyUserUpdatedIndexName = "stats_user_updated_at"
)
type commandRename struct {
old string
@@ -34,6 +41,9 @@ func InitStore(ctx context.Context, statsColl, systemColl storage.Collection) er
if err := ensureUsageIndexes(ctx, mongoColl); err != nil {
return err
}
if err := dropIndexIfExists(ctx, mongoColl, statsLegacyUserUpdatedIndexName); err != nil {
return err
}
}
if err := runMiscCommandRenameMigration(ctx, statsColl, systemColl); err != nil {
return err
@@ -130,15 +140,15 @@ func ensureUsageIndexes(ctx context.Context, coll *mongo.Collection) error {
models := []mongo.IndexModel{
{
Keys: bson.D{bsonField("cmd", 1), bsonField("n", -1), bsonField("user", 1)},
Options: options.Index().SetName("stats_cmd_n_user"),
Options: options.Index().SetName(statsCommandUsersIndexName),
},
{
Keys: bson.D{bsonField("uid", 1), bsonField("n", -1), bsonField("cmd", 1)},
Options: options.Index().SetName("stats_uid_n_cmd"),
Options: options.Index().SetName(statsUserCommandsIndexName),
},
{
Keys: bson.D{bsonField("user", 1), bsonField("updatedAt", -1)},
Options: options.Index().SetName("stats_user_updated_at"),
Keys: bson.D{bsonField("user", 1), bsonField("uid", 1)},
Options: options.Index().SetName(statsUsernameLookupIndexName),
},
}
if _, err := coll.Indexes().CreateMany(ctx, models); err != nil {
@@ -146,3 +156,31 @@ func ensureUsageIndexes(ctx context.Context, coll *mongo.Collection) error {
}
return nil
}
func dropIndexIfExists(ctx context.Context, coll *mongo.Collection, name string) error {
cur, err := coll.Indexes().List(ctx)
if err != nil {
return fmt.Errorf("stats list indexes before drop %s: %w", name, err)
}
defer func() { _ = cur.Close(ctx) }()
for cur.Next(ctx) {
var doc struct {
Name string `bson:"name"`
}
if err := cur.Decode(&doc); err != nil {
return fmt.Errorf("stats decode index before drop %s: %w", name, err)
}
if doc.Name != name {
continue
}
if err := coll.Indexes().DropOne(ctx, name); err != nil {
return fmt.Errorf("stats drop legacy index %s: %w", name, err)
}
return nil
}
if err := cur.Err(); err != nil {
return fmt.Errorf("stats index cursor before drop %s: %w", name, err)
}
return nil
}
+22 -5
View File
@@ -7,6 +7,10 @@ import (
"testing"
"time"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
"github.com/tiennm99/miti99bot/internal/storage"
)
@@ -36,14 +40,24 @@ func TestInitStore_MongoCreatesIndexes(t *testing.T) {
statsColl := provider.Collection("stats")
systemColl := provider.Collection("system")
if err := InitStore(ctx, statsColl, systemColl); err != nil {
t.Fatalf("InitStore: %v", err)
}
rawStatsColl, ok := storage.MongoCollection(statsColl)
if !ok {
t.Fatal("stats collection is not Mongo-backed")
}
if _, err := rawStatsColl.Indexes().CreateOne(ctx, mongo.IndexModel{
Keys: bson.D{bsonField("user", 1), bsonField("updatedAt", -1)},
Options: options.Index().SetName(statsLegacyUserUpdatedIndexName),
}); err != nil {
t.Fatalf("seed legacy index: %v", err)
}
if err := InitStore(ctx, statsColl, systemColl); err != nil {
t.Fatalf("InitStore: %v", err)
}
if err := InitStore(ctx, statsColl, systemColl); err != nil {
t.Fatalf("InitStore second run: %v", err)
}
cur, err := rawStatsColl.Indexes().List(ctx)
if err != nil {
t.Fatalf("list indexes: %v", err)
@@ -63,9 +77,12 @@ func TestInitStore_MongoCreatesIndexes(t *testing.T) {
if err := cur.Err(); err != nil {
t.Fatalf("index cursor: %v", err)
}
for _, name := range []string{"stats_cmd_n_user", "stats_uid_n_cmd", "stats_user_updated_at"} {
for _, name := range []string{statsCommandUsersIndexName, statsUserCommandsIndexName, statsUsernameLookupIndexName} {
if !found[name] {
t.Fatalf("missing index %s; indexes=%v", name, found)
}
}
if found[statsLegacyUserUpdatedIndexName] {
t.Fatalf("legacy index %s was not dropped; indexes=%v", statsLegacyUserUpdatedIndexName, found)
}
}
+1 -2
View File
@@ -439,8 +439,7 @@ func (s *mongoUsageStore) userIDByUsername(ctx context.Context, username string)
"deleted": bson.M{"$ne": true},
},
options.FindOne().
SetProjection(bson.M{"uid": 1}).
SetSort(bson.D{bsonField("updatedAt", -1)}),
SetProjection(bson.M{"uid": 1}),
).Decode(&doc)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {