Uncategorized

Héritage ?

J’ai un problème récurrent de conception et je ne suis pas sûr d’avoir le vocabulaire technique pour l’exprimer, et donc pour rechercher exactement une solution sur l’internet mondial. Parce que, forcément, quelqu’un a déjà élaboré une solution sympathique pour résoudre ce problème. Problème qui est le suivant :

Je possède une collection d’objet de types différents (des Artiste, des Albums, des Livres, des Utilisateurs etc…) stockés chacun dans sa proble table de données comme il est coutume de faire.
À chacune des instances de ces objets, (Britney Spears, Stade 2, The Baroque Cycle, toto01 etc…) je veux pouvoir associer une série de commentaires  dont le format ne dépend pas de l’objet auquel il est attribué : je souhaite stocker qui a commenté, le texte de son commentaire et la date du commentaire. Et évidemment l’association.

Comme ça, c’est simple. Pour faire ça, il y a mille manières. J’en voudrais une qui soit efficace et maligne et qui réponde aux contraintes suivantes :
– Je voudrais pouvoir récupérer les n derniers commentaires, des p types tous confondus, et pour chacun toutes les infos de l’objet associé en  un nombre de requêtes ne dépendant de n qu’au plus en o(log n), et ne dépendant pas de p.
– Je voudrais pouvoir récupérer les derniers commentaires d’un objet précis en o(1) requête.
– Pareillement pour les derniers commentaires sur un type (max o(1) requête)
– Je ne souhaite pas dupliquer mes commentaires.
– En Mysql. (hahaha)

Voilà, si quelqu’un a une réponse à cette question qui me chagrine, je la prends aisément. En attendant, je vais continuer avec mes bricolages, mes UNIONs de la mort et mes duplications de commentaires.

Standard

14 thoughts on “Héritage ?

  1. @c_chep says:

    Problème intéressant. Je reformule pour voir si je comprends les données. Ton schéma ressemble en gros à ça:

    create table artist(id primary key, name varchar(32));
    create table album(id primary key, имя varchar(34));
    create table book(id primary key, title varchar(39));
    create table user(id primary key, login varchar(16));
    /* etc. d’autres entités, quantité arbitraire mais codable et constante à la cible */

    create table comment(id primary key, content_rt varchar(4096));

    create table comment_to_stuff(cmt_id foreign key references comment.id,
    /* ????… */,
    );
    create unique index comment_id on comment_to_stuff(cmt_id); — le commentaire porte sur UN objet à la fois et un seul.

    Ce que tu veux faire:

    1)

    2) récupérer tous (ou les derniers) commentaires pour un objet dont on connait (type, id), en une seule requête

  2. Truffe says:

    Hellou,

    Je crois que je pourrais répondre par un “bon courage”, mais ça serait mesquin.

    En bref, tu veux regrouper des objets de format distinct pour pouvoir les manipuler.

    Fait une vue qui est une union de select convertissant tes tables au mêmes formats.

    Pour faire simple ça ressemble grosso modo à ça :
    create view ma_vue
    select commentaire, date_du_commentaire, type, nom de l’artiste
    from ma_table_artiste
    union
    select commentaire, date_du_commentaire, type, nom de l’album
    from ma_table_album

    Et après tu manipule ta vue comme une table.
    select * from ma_vue where date_du_commentaire > today()

    Je ne suis pas sûr de la syntaxe de création de vue ni si la fonction today() fonctionne en mysql, mais l’idée est là.

    Bref, bon courage

  3. Ju(...) says:

    @c_chep : tu as tout compris l’essence du problème mais :(j’enchaîne sur une autre réponse)

    @Truffe : ta solution fonctionne si les types de chaque colonne sont interchangeable (exemple là, tu ne gardes que les “noms” des objets liés) Quid de si, par exemple dans le cas d’un album, je veux stocker le nombre de chansons, et pour un artiste sa bio etc… avec un nombre de colonne disparate ?

  4. Truffe says:

    @Ju(…) : La première étape est avant tout d’uniformiser les données. Quand on essaye de consolider des choux et des carottes il faut définir la manière de les agréger (poids, nombre, le nombre de feuille), on n’y coupe pas.

  5. Ju(...) says:

    @Truffe en fait, c’est la technique que j’utilise, mais ça m’oblige potentiellement à changer la forme de la vue à chaque fois que je veux rajouter un type. Et j’ai abandonné toute idée de pouvoir faire une jointure supplémentaire (attraper l’artiste de album commenté par ex)(sauf à joindre dans la vue carrément)

  6. @c_chep says:

    donc, pour la question 1: on devrait pouvoir y arriver, avec une base SQL normalement constituée (normalement, MySQL est à ce stade sur ce point depuis longtemps) à faire un truc de ce genre:

    create table chapo(objtype varchar(3), id integer auto_increment
    primary key(objtype, id));
    create table artist(id integer, имя varchar(32),
    foreign key (id) referenecs chapo(id));
    create table album(id integer, name varchar(34),
    foreign key (id) referenecs chapo(id));
    create table book(id integer, title varchar(39),
    foreign key (id) referenecs chapo(id));
    create table user(id integer, login varchar(16),
    foreign key (id) references chapo(id));

    create table comment_to_stuff(cmt_id integer,
    obj_typ varchar(3), obj_id integer,

    foreign key (cmt_id) references comment(id),
    foreign key (obj_typ, obj_id) references chapo(objtype, id)
    );

  7. @c_chep says:

    select c.id, c.date, u.login, c.content_rt
    artist.имя art_name, album.name alb_name,
    book.title bok_title, user.login usr_login

  8. @c_chep says:

    from comment c
    inner join user a on on c.author = a.id
    inner join comment_to_stuff cts on c.id = cts.cmt_id
    inner join chapo o
    on cts.obj_typ = o.objtype and cts.obj_id = o.id

  9. @c_chep says:

    left outer join artist
    on (o.id = artist.id and o.objtype = ‘ART’)
    left outer join album
    on (o.id = album.id and o.objtype = ‘ALB’)
    left outer join book
    on (o.id = book.id and o.objtype = ‘BOK’)
    left outer join user
    on (o.id = user.id and o.objtype = ‘USR’)

  10. @c_chep says:

    2) récupérer tous (ou les derniers) commentaires pour un objet dont on connait (type, id), en une seule requête

    select c.id, c.date, c.content_rt
    from comment c
    inner join comment_to_stuff cts on c.id = cts.cmt_id
    where cts.obj_typ = ${objtype} and cts.obj_id=${objid}
    order by c.date desc
    limit 42

Comments are closed.