8723 sujets

Développement web côté serveur, CMS

Bonsoir,

Ma question du jour : est-il courant d'avoir plusieurs requêtes SQL pour une page web ? Dans l'idéal j'essaie de regrouper les requêtes mais je n'y arrive pas toujours (cf. le post suivant comme exemple).

Je tente de construire des requêtes SQL pour mon petit CMS maison (sous Postgres). Ça avance lentement (vu le peu de temps libre dont je dispose) mais sûrement. J'apprends pleins de trucs mais mon problème principal est que je reste un amateur et que, en tant que tel, je manque de feedback...

Modifié par Olivier C (17 Apr 2024 - 13:22)
*** Par exemple, voici le script backend pour une page établissant une liste de tous les articles liés à un mot clef (sous WordPress ce serait le template tag.php) pour laquelle j'ai dû faire deux requêtes (pour une bricole en plus, la deuxième requête c'est juste pour récupérer le nom du tag) ; c'est sous Fastify, mais c'est presque comme Express.js :
import { dataConversion } from '../utils/dataConversion.js'

async function modifyData(req, data) {
  data.url = req.url
  data.name = `${data.tagName} <span>.&nbsp;Étiquette</span>`
  data.title = data.name.concat(' . ', process.env.SITE_NAME).replace(/(<([^>]+)>)/gi, '').replace(/&nbsp;/gi, ' ')
  data.description = `Article liés à l'étiquette &quot;${data.tagName}&quot; pour le site ${process.env.SITE_NAME}`
}

export async function getTag(req, res) {
  const client = await this.pg.connect()
  const query = `
    SELECT
      a._id,
      a._name,
      a._alternative_headline,
      a._slug,
      a._created_at,
      a._modified_at,
      a._type,
      a._description,
      a._author_id,
      a._status,
      a._is_restricted_read,
      jsonb_build_object(
        '_username', ac._username,
        '_display_name', ac._display_name
      ) AS _account,
      jsonb_build_object(
        '_given_name', p._given_name,
        '_additional_name', p._additional_name,
        '_family_name', p._family_name,
        '_usual_name', p._usual_name,
        '_nickname', p._nickname,
        '_prefix', p._prefix,
        '_suffix', p._suffix,
        '_url', p._url
      ) AS _author
    FROM
      __article a
    LEFT JOIN
      __account ac ON a._author_id = ac._id
    LEFT JOIN
      __person p ON ac._person_id = p._id
    LEFT JOIN
      __tag_to_article ta ON a._id = ta._article_id
    LEFT JOIN
      __tag t ON ta._tag_id = t._id
    WHERE
      t._slug = $1
    ORDER BY
      a._created_at DESC
    LIMIT
      50
    `
  const query2 = `SELECT _name FROM __tag WHERE _slug = $1`
  let data = {}
  try {
    const { rows } = await client.query(query, [req.params.slug])
    const tagName = await client.query(query2, [req.params.slug])
    if (!rows[0] || !tagName.rows[0]) return res.code(404).view('404')
    data.articles = await Promise.all(rows.map(x => dataConversion(x)))
    data.tagName = await dataConversion(tagName.rows[0]._name)
    modifyData(req, data)
    console.log(data)
    //return data
    return res.view('index', { data })
  } finally {
    client.release()
  }
}

Ce qui donne :
{
  articles: [
    {
      id: 2,
      // les items récupérés...
    },
    {
      id: 4,
      // les items récupérés...
    },
    {
      id: 5,
      // les items récupérés...
    }
  ],
  tagName: 'Anthropologie',
  url: '/tag/anthropologie',
  name: 'Anthropologie <span>.&nbsp;Étiquette</span>',
  title: 'Anthropologie . Étiquette . NomDuSite',
  description: "Article liés à l'étiquette &quot;Anthropologie&quot; pour le site NomDuSite"
}

Auparavant j'avais fait plus simple et réussi à concaténer :
export async function getTag(req, res) {
  const client = await this.pg.connect()
  const query = `
    SELECT
      a._id,
      a._name,
      a._alternative_headline,
      a._slug,
      a._created_at,
      a._modified_at,
      a._type,
      a._description,
      a._author_id,
      a._status,
      a._is_restricted_read,
      jsonb_build_object(
        '_username', ac._username,
        '_display_name', ac._display_name
      ) AS _account,
      jsonb_build_object(
        '_given_name', p._given_name,
        '_additional_name', p._additional_name,
        '_family_name', p._family_name,
        '_usual_name', p._usual_name,
        '_nickname', p._nickname,
        '_prefix', p._prefix,
        '_suffix', p._suffix,
        '_url', p._url
      ) AS _author,
      t._name AS _tag_name
    FROM
      __article a
    LEFT JOIN
      __account ac ON a._author_id = ac._id
    LEFT JOIN
      __person p ON ac._person_id = p._id
    LEFT JOIN
      __tag_to_article ta ON a._id = ta._article_id
    LEFT JOIN
      __tag t ON ta._tag_id = t._id
    WHERE
      t._slug = $1
    ORDER BY
      a._created_at DESC
    LIMIT
      50
    ` // @note Pour l'instant le nom du tag recherché est dupliqué dans chaque article retourné @todo À récupérer au niveau supérieur, à la racine du return de la recherche SQL.
  let data = {}
  try {
    const { rows } = await client.query(query, [req.params.slug])
    if (!rows[0]) return res.code(404).view('404')
    data.articles = await Promise.all(rows.map(x => dataConversion(x)))
    modifyData(req, data)
    console.log(data)
    //return data
    return res.view('index', { data })
  } finally {
    client.release()
  }
}

Le problème dans ce cas, c'est que le nom du tag ("_tag_name") se retrouve lié à chaque article récupéré, et donc dupliqué d'autant. Ce qui rendait la réponse moins propre :
{
  articles: [
    {
      id: 2,
      // les items récupérés...
      tagName: 'Anthropologie'
    },
    {
      id: 4,
      // les items récupérés...
      tagName: 'Anthropologie'
    },
    {
      id: 5,
      // les items récupérés...
      tagName: 'Anthropologie'
    }
  ],
  url: '/tag/anthropologie',
  name: 'Anthropologie <span>.&nbsp;Étiquette</span>',
  title: 'Anthropologie . Étiquette . NomDuSite',
  description: "Article liés à l'étiquette &quot;Anthropologie&quot; pour le site NomDuSite"
}

Modifié par Olivier C (17 Apr 2024 - 01:08)
Après avoir essayé de limiter le nombre de requête au minimum, je me suis rendu compte que
1) ça conduisait à des requêtes très complexes avec un code php très lourd pour retrouver les informations et les réorganiser selon la logique de la page à produire
2) que dans beaucoup de cas c'était impossible en pratique de réduire le nombre de requêtes en dessous d'un 3 ou 4
J'ai donc décidé de donner priorité à la logique des traitements et de ne plus me soucier du nombre de requêtes, quitte à fusionner plusieurs requêtes quand je suis arrivé à faire ce que je veux.
Je suis du même avis que PapyJP

Tant pis j'ai 2, 3 ou plus de requêtes pour une page web... je préfère avoir un code facilement debuggable et factoriser que tout dans une grosse requêtes complexe.
Merci à vous pour vos retours respectifs.
Si d'autres alsanautes veulent donner leur avis je suis preneur.