Saltar al contenido principal

Hashtags y Tendencias — Referencia técnica

← Volver a Hashtags y Tendencias

Dónde vive esto

Backend

  • apps/backend/graphql/resolvers/hashtag.resolver.js — resuelve hashtag, hashtagByName, searchHashtags, trendingHashtags, hashtagStats
  • apps/backend/graphql/types/hashtag.type.js — tipo SDL Hashtag y esquema de consultas
  • apps/backend/managers/post-managers/hashtag.manager.js — cálculo del puntaje de tendencia, lógica de búsqueda y consulta
  • apps/backend/data-access-services/post/hashtag.access-service.js — acceso a la base de datos de hashtags (trasladado a data-access-services/post/ junto con los demás servicios de acceso relacionados con publicaciones)
  • apps/backend/graphql/resolvers/user-mentions-tags.resolver.js — implementa usersMentionedBy, usersIMentioned, removeTag, removeMention (el user.resolver.js monolítico al que este documento apuntaba antes ya no existe — los resolvers de usuario se dividieron en muchos archivos)
  • Verificado pero vale la pena señalarlo: post-hashtag.access-service.js (ahora data-access-services/post/post-hashtag.access-service.js) y conversation-hashtag.access-service.js (ahora data-access-services/message/conversation-hashtag.access-service.js) están conectados — post.manager.js#createPost enlaza cada hashtag extraído mediante el primero (este documento decía antes que ninguno era llamado por ningún manager — corregido). Por separado, los métodos subyacentes de removeTag en mentions-tags.manager.jsgetUsersMentionedBy/getUsersIMentioned — siguen siendo stubs TODO/simulados que devuelven datos vacíos sin importar la entrada (removeTag en sí fue corregido en esta sesión — ver la checklist abajo). myMentions, mentionsInContent, mentionUser y tagUser ya no existen en absoluto en el esquema (fueron eliminados — ver la checklist abajo), así que ignora cualquier referencia a ellos a continuación como algo histórico.

Frontend

Checklist de implementación técnica

  • trendingHashtags — conectado en hashtag.resolver.js, llama a hashtag.manager.js#getTrendingHashtags; consumido por la fila de chips "Tendencias" de HashtagPage.tsx (este documento decía antes que no había ningún consumidor en el frontend — corregido)
  • searchHashtags — conectado en hashtag.resolver.js; consumido por la superposición de búsqueda móvil de HomePage.tsx
  • Extracción automática de hashtags al crear una publicación — post.manager.js:217 llama a hashtagManager.extractAndCreateHashtags; combinado con getByHashtag/postsByHashtag, esto sustenta el feed real de /hashtag/[tag] (HashtagPage.tsx) y los enlaces de hashtag en los que se puede hacer clic que PostCard.tsx renderiza mediante linkifyText — ver Publicaciones y Feed
  • hashtagByName / hashtagStats — conectado en hashtag.resolver.js; consumido por el encabezado de HashtagPage.tsx (total de publicaciones / personas distintas) — la propia cuadrícula de publicaciones del feed del hashtag sigue usando postsByHashtag, no estos dos (este documento decía antes que ninguno tenía un consumidor en el frontend — corregido)
  • PostHashtag (publicaciones) y ConversationHashtag (dentro del chat) están ambos conectados — post.manager.js#createPost enlaza cada hashtag extraído mediante post-hashtag.access-service.js; message.manager.js#createMessage extrae los #hashtags del texto del mensaje, los enlaza a la conversación mediante conversation-hashtag.access-service.js (sin duplicados) e incrementa el uso; hashtag.access-service.js#getTrending cuenta los enlaces recientes de hashtags de conversación junto con los de publicaciones, de modo que los hashtags dentro del chat también aparecen en las tendencias.
  • usersMentionedBy / usersIMentioned — conectado en user-mentions-tags.resolver.js; consumido por Ajustes → Historial de menciones (MentionHistoryPage.tsx, en /settings/mentions) — pero los métodos subyacentes de mentions-tags.manager.js todavía son stubs TODO/simulados que siempre devuelven un resultado vacío, así que las pestañas se renderizan y consultan correctamente pero nunca muestran datos reales de menciones
  • removeTagCorregido en esta sesión, dos errores: (1) el resolver antes desestructuraba un argumento tagId inexistente, por lo que toda llamada fallaba sin importar la entrada — ahora lee los argumentos reales userId/contentType/contentId que declara el SDL y devuelve el booleano real del manager. (2) mentions-tags.manager.js#removeTag era un stub (console.log, sin escritura en la base de datos) — ahora realiza una eliminación real de PostMention, restringida a contenido de tipo POST, y autorizada solo al usuario etiquetado o al propietario de la publicación (obtenido mediante postAccessService.findById); cualquier otro usuario recibe permissions.cannot_remove_tag. removeMention(mentionId) sigue siendo una mutación separada y más simple para la misma fila de PostMention, respaldada por post-mention.manager.js#deleteMention.
  • myMentions / mentionsInContent / mentionUser / tagUsereliminados del SDL de mentions-tags.type.js. Eran campos muertos sin resolver y sin consumidor en el frontend, que duplicaban conceptos ya cubiertos por el sistema real de etiquetado basado en PostMention (tocar para etiquetar + @menciones en el pie de foto, registradas mediante post-mention.access-service.js), así que se eliminaron en lugar de implementarse, para mantener el esquema honesto.

Modelo Hashtag

CampoDescripción
nameHashtag original (mayúsculas/minúsculas mixtas)
normalizedNameVersión normalizada en minúsculas
usageCountConteo total de uso
trendingScorePuntaje de tendencia calculado
lastUsedAtTimestamp del uso más reciente

Queries

trendingHashtags devuelve los N hashtags principales ordenados por trendingScore, que combina la velocidad reciente con el uso general. Úsalo para la fila de tendencias de la página Explorar.

searchHashtags autocompleta una cadena parcial de hashtag — llámalo en cada pulsación de tecla mientras el usuario escribe # en el compositor de publicaciones. Los resultados se ordenan por usageCount.

hashtagByName obtiene un solo hashtag por su nombre exacto — útil al navegar a una página de hashtag (p. ej. /hashtag/photography).

hashtagStats devuelve el número total de publicaciones y usuarios únicos que han usado un hashtag — se muestra en la página de detalle del hashtag.

query TrendingHashtags($limit: Int) {
trendingHashtags(limit: $limit) {
id name usageCount trendingScore lastUsedAt
}
}

query SearchHashtags($query: String!, $limit: Int) {
searchHashtags(query: $query, limit: $limit) { id name usageCount }
}

query HashtagByName($name: String!) {
hashtagByName(name: $name) { id name usageCount trendingScore }
}

query HashtagStats($hashtagId: ID!) {
hashtagStats(hashtagId: $hashtagId) { totalPosts totalUsers }
}

Hashtags en conversaciones

Los mensajes también pueden llevar hashtags. La tabla ConversationHashtag los indexa para la búsqueda dentro del chat.

Menciones de usuarios

myMentions, mentionsInContent, mentionUser y tagUser no existen en el esquema — fueron eliminados (ver la checklist arriba); ignora cualquier referencia anterior a ellos.

removeMention elimina una fila específica de PostMention y es la mutación que sí funciona de extremo a extremo — puede llamarla tanto el propietario de la publicación como el usuario mencionado (post-mention.manager.js#deleteMention). removeTag (argumentos userId/contentType/contentIdcontentType debe ser POST, el único tipo de contenido para el que hoy están modeladas las etiquetas) ahora también funciona de extremo a extremo: elimina la fila PostMention correspondiente, restringido al usuario etiquetado o al propietario de la publicación — ver la checklist arriba para los dos errores corregidos en esta sesión.

# Remove a specific mention (post owner or the mentioned user can call this)
mutation RemoveMention($mentionId: ID!) {
removeMention(mentionId: $mentionId)
}

# Tagged user or the post's owner can call this
mutation RemoveTag($userId: ID!, $contentType: String!, $contentId: ID!) {
removeTag(userId: $userId, contentType: $contentType, contentId: $contentId)
}

Etiquetas de contenido

ContentTag es una etiqueta gestionada por el sistema, aplicada automáticamente mediante clasificación por IA — distinta de los hashtags creados por los usuarios. Las etiquetas describen la categoría temática de publicaciones y conversaciones.

CampoDescripción
nameEtiqueta (p. ej. photography, sports)
categoryGrupo de categoría de la etiqueta
usageCountNúmero de elementos etiquetados
confidenceAvgPuntaje promedio de confianza de la IA (0–1)

Las etiquetas se aplican a publicaciones mediante PostContentTag y a conversaciones mediante ConversationContentTag. Impulsan el motor de intereses de contenido — consulta Publicaciones y Feed para ver cómo se rastrea la afinidad del usuario por cada etiqueta.

Historial de menciones

usersMentionedBy muestra a qué usuarios suele mencionar una cuenta dada — útil para una vista analítica o de relaciones. usersIMentioned muestra a quién ha mencionado recientemente el usuario actual. Ambas son consumidas por Ajustes → Historial de menciones (MentionHistoryPage.tsx), pero su implementación subyacente en mentions-tags.manager.js sigue siendo un stub TODO/simulado que siempre devuelve una lista vacía — las pestañas están completamente conectadas de extremo a extremo pero no mostrarán datos reales de menciones hasta que ese manager se implemente contra PostMention/MessageMention.

query UsersMentionedBy($userId: ID!, $limit: Int) {
usersMentionedBy(userId: $userId, limit: $limit) { id username }
}

query UsersIMentioned($limit: Int) {
usersIMentioned(limit: $limit) { id username }
}