Skip to content

Commit fdaa5b3

Browse files
authored
Optimize query for getting tags for a level (#943)
Optimizes the query used to get the tags for a level. After adding a few tag relations to a few levels on my server and then doing similar testing as in #842, I've got the following results: With the new query: ``` [09/05/25 11:12:42] [Info] [Request] Served request to 127.0.0.1:36562: 200 OK on GET '/api/v3/levels/newest?count=100' (260ms) [09/05/25 11:12:42] [Info] [Request] Served request to 127.0.0.1:36584: 200 OK on GET '/api/v3/levels/newest?count=100' (262ms) [09/05/25 11:12:43] [Info] [Request] Served request to 127.0.0.1:36608: 200 OK on GET '/api/v3/levels/newest?count=100' (250ms) [09/05/25 11:12:43] [Info] [Request] Served request to 127.0.0.1:36626: 200 OK on GET '/api/v3/levels/newest?count=100' (260ms) [09/05/25 11:12:44] [Info] [Request] Served request to 127.0.0.1:36650: 200 OK on GET '/api/v3/levels/newest?count=100' (255ms) ``` With the old query: ``` [09/05/25 11:13:00] [Info] [Request] Served request to 127.0.0.1:34600: 200 OK on GET '/api/v3/levels/newest?count=100' (504ms) [09/05/25 11:13:01] [Info] [Request] Served request to 127.0.0.1:34608: 200 OK on GET '/api/v3/levels/newest?count=100' (500ms) [09/05/25 11:13:01] [Info] [Request] Served request to 127.0.0.1:34626: 200 OK on GET '/api/v3/levels/newest?count=100' (491ms) [09/05/25 11:13:02] [Info] [Request] Served request to 127.0.0.1:34652: 200 OK on GET '/api/v3/levels/newest?count=100' (505ms) [09/05/25 11:13:03] [Info] [Request] Served request to 127.0.0.1:34664: 200 OK on GET '/api/v3/levels/newest?count=100' (507ms) ```
2 parents db5af41 + 1c21dbf commit fdaa5b3

3 files changed

Lines changed: 12 additions & 15 deletions

File tree

Refresh.Database/GameDatabaseContext.Relations.cs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -748,19 +748,16 @@ public void AddTagRelation(GameUser user, GameLevel level, Tag tag)
748748
});
749749
}
750750

751-
public IEnumerable<TagLevelRelation> GetTagsForLevel(GameLevel level)
752-
{
753-
IQueryable<TagLevelRelation> levelTags = this.TagLevelRelationsIncluded.Where(t => t.Level == level);
754-
755-
IEnumerable<TagLevelRelation> tags = levelTags
756-
.AsEnumerableIfRealm() // TODO: optimize for postgres when realm is deleted
757-
.GroupBy(t => t.Tag).Select(g => g.First())
758-
// ^ is equivalent to .DistinctBy(t => t._Tag)
759-
.AsEnumerable()
760-
.OrderByDescending(t => levelTags.Count(levelTag => levelTag.Tag == t.Tag));
761-
762-
return tags;
763-
}
751+
public IQueryable<Tag> GetTagsForLevel(GameLevel level)
752+
=> this.TagLevelRelations.Where(t => t.LevelId == level.LevelId)
753+
.GroupBy(t => t.Tag)
754+
.Select(g => new { Tag = g.Key, Count = g.Count() })
755+
.OrderByDescending(t => t.Count)
756+
.Select(g => g.Tag);
757+
758+
public IQueryable<TagLevelRelation> GetTagRelationsForLevel(GameLevel level)
759+
=> this.TagLevelRelationsIncluded.Where(t => t.LevelId == level.LevelId)
760+
.OrderByDescending(t => t.Timestamp);
764761

765762
#endregion
766763
}

Refresh.Interfaces.APIv3/Endpoints/DataTypes/Response/Levels/ApiGameLevelResponse.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public class ApiGameLevelResponse : IApiResponse, IDataConvertableFrom<ApiGameLe
100100
PhotosTaken = level.Statistics.PhotoInLevelCount,
101101
LevelComments = level.Statistics.CommentCount,
102102
Reviews = level.Statistics.ReviewCount,
103-
Tags = dataContext.Database.GetTagsForLevel(level).Select(t => t.Tag),
103+
Tags = dataContext.Database.GetTagsForLevel(level),
104104
IsModded = level.IsModded,
105105
};
106106
}

Refresh.Interfaces.Game/Types/Levels/GameMinimalLevelResponse.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ public static GameMinimalLevelResponse FromHash(string hash, DataContext dataCon
184184

185185
if (dataContext.Game == TokenGame.LittleBigPlanet1)
186186
{
187-
response.Tags = string.Join(',', dataContext.Database.GetTagsForLevel(old).Select(t => t.Tag.ToLbpString()));
187+
response.Tags = string.Join(',', dataContext.Database.GetTagsForLevel(old).Select(t => t.ToLbpString()));
188188
}
189189

190190
response.IconHash = dataContext.Database.GetAssetFromHash(old.IconHash)?.GetAsIcon(dataContext.Game, dataContext) ?? old.IconHash;

0 commit comments

Comments
 (0)