diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock
index 99abaa02ea1eefee9bd2fc69712498d8fa4f3a84..370b76eea330a3d9b2388f6a26d62b2ca34c4f1f 100644
--- a/src/rust/Cargo.lock
+++ b/src/rust/Cargo.lock
@@ -1745,6 +1745,7 @@ dependencies = [
  "commons",
  "diesel",
  "diesel_migrations",
+ "hashbrown 0.13.2",
  "kurisu_api",
  "lektor_c_compat",
  "serde",
diff --git a/src/rust/lektor_db/Cargo.toml b/src/rust/lektor_db/Cargo.toml
index dceba9b336cc7a91fcad9343ceec3772ae3ccd14..d1d8f3594ea72d1bd54e8228ed19e82c0b5d741c 100644
--- a/src/rust/lektor_db/Cargo.toml
+++ b/src/rust/lektor_db/Cargo.toml
@@ -11,6 +11,7 @@ doctest = false
 [dependencies]
 serde.workspace = true
 thiserror.workspace = true
+hashbrown.workspace = true
 
 diesel_migrations = "2"
 diesel = { version = "2", default-features = false, features = ["sqlite"] }
diff --git a/src/rust/lektor_db/src/connexion.rs b/src/rust/lektor_db/src/connexion.rs
index efedeaf94968542dd2e5090582d37376fa7a5548..120f90b0453f029f65fc19baa2db9642ee547db4 100644
--- a/src/rust/lektor_db/src/connexion.rs
+++ b/src/rust/lektor_db/src/connexion.rs
@@ -1,5 +1,5 @@
-use crate::{models::*, uri::LktUri, *};
-use diesel::connection::DefaultLoadingMode;
+use crate::{models::*, types::*, uri::LktUri, *};
+use hashbrown::HashMap;
 use kurisu_api::v1 as api_v1;
 
 /// Create a connexion to a database and run automatically the migrations.
@@ -275,39 +275,52 @@ impl LktDatabaseConnection {
         }
     }
 
+    /// Get basic information about a kara, like its source, title, origin, the
+    /// laguages, etc. Here we don't get the kara makers as it's not an
+    /// essential information.
+    pub fn get_kara_info(&mut self, local_id: i64) -> LktDatabaseResult<KaraInfo> {
+        todo!("get info for kara {local_id}")
+    }
+
     /// Get all infos about a kara, its metadata, its tags, repo, repo id,
-    /// languages, karamakers...
-    pub fn get_kara_info(
-        &mut self,
-        local_id: i64,
-    ) -> LktDatabaseResult<Vec<(String, Option<String>)>> {
-        let repo: String = with_dsl!(repo_kara => repo_kara
+    /// karamakers...
+    pub fn get_kara_tags(&mut self, local_id: i64) -> LktDatabaseResult<KaraTags> {
+        let (repo, repo_id) = with_dsl!(repo_kara => repo_kara
             .filter(local_kara_id.is(local_id))
             .inner_join(schema::repo::table)
-            .select(schema::repo::name)
-            .first::<String>(&mut self.sqlite)?
+            .select((schema::repo::name, repo_kara_id))
+            .first::<(String, i64)>(&mut self.sqlite)?
         );
-        let mut ret = vec![(String::from("repo"), Some(repo))];
 
-        for kara_maker in with_dsl!(kara => kara
+        let kara_makers: Vec<String> = with_dsl!(kara => kara
             .filter(id.is(local_id))
             .inner_join(schema::kara_maker::table)
             .select(schema::kara_maker::name)
-            .load_iter::<String, DefaultLoadingMode>(&mut self.sqlite)?
-        ) {
-            ret.push((String::from("karamaker"), Some(kara_maker?)));
-        }
+            .load::<String>(&mut self.sqlite)?
+        );
 
-        for tag_entry in with_dsl!(kara_tag => kara_tag
+        let tags_raw: Vec<(String, Option<String>)> = with_dsl!(kara_tag => kara_tag
             .filter(kara_id.is(local_id))
             .inner_join(schema::tag::table)
             .select((schema::tag::name, value))
-            .load_iter::<(String, Option<String>), DefaultLoadingMode>(&mut self.sqlite)?
-        ) {
-            let (key, value) = tag_entry?;
-            ret.push((key, value))
+            .load::<(String, Option<String>)>(&mut self.sqlite)?
+        );
+        let mut tags: HashMap<String, Vec<String>> = Default::default();
+        for (tag, value) in tags_raw.into_iter() {
+            match tags.get_mut(&tag) {
+                Some(values) => values.extend(value),
+                None => {
+                    let values: Vec<_> = value.into_iter().collect();
+                    tags.insert(tag, values);
+                }
+            }
         }
 
-        Ok(ret)
+        Ok(KaraTags {
+            repo,
+            repo_id,
+            kara_makers,
+            tags,
+        })
     }
 }
diff --git a/src/rust/lektor_db/src/lib.rs b/src/rust/lektor_db/src/lib.rs
index a46a3e53a7b7d8a178d9ccc6733d4de5dfdde6d7..add72f281086040fe052ad7b4ec92f3242be49d6 100644
--- a/src/rust/lektor_db/src/lib.rs
+++ b/src/rust/lektor_db/src/lib.rs
@@ -6,6 +6,7 @@ pub mod connexion;
 pub mod error;
 pub mod models;
 pub mod queue;
+pub mod types;
 pub mod uri;
 
 pub(self) mod schema;
diff --git a/src/rust/lektor_db/src/types.rs b/src/rust/lektor_db/src/types.rs
new file mode 100644
index 0000000000000000000000000000000000000000..76a9ed736b088298621b9e13e7985ed90510ac7b
--- /dev/null
+++ b/src/rust/lektor_db/src/types.rs
@@ -0,0 +1,19 @@
+use hashbrown::HashMap;
+
+pub struct KaraInfo {
+    pub local_id: i64,
+
+    pub source_name: String,
+    pub song_title: String,
+    pub song_origin: String,
+    pub song_type: String,
+
+    pub languages: Vec<String>,
+}
+
+pub struct KaraTags {
+    pub repo_id: i64,
+    pub repo: String,
+    pub kara_makers: Vec<String>,
+    pub tags: HashMap<String, Vec<String>>,
+}