Executar consultas do Data Explorer com a API do Discourse

:bookmark: Este guia explica como usar a API do Discourse para criar, executar e gerenciar consultas com o plugin Data Explorer.

:person_raising_hand: Nível de usuário necessário: Administrador

Virtualmente qualquer ação que possa ser realizada através da interface do usuário do Discourse também pode ser acionada com a API do Discourse.

Este documento fornece uma visão geral abrangente para utilizar a API especificamente em conjunto com o plugin Data Explorer.

Para uma visão geral de como encontrar a solicitação de API correta para uma ação, consulte: Reverse engineer the Discourse API .

Executando uma consulta do Data Explorer

Para executar uma consulta do Data Explorer via API, faça uma solicitação POST para /admin/plugins/explorer/queries/<query-id>/run. Você pode encontrar o ID da consulta visitando-a através do seu site Discourse e verificando o parâmetro id na barra de endereço.

Abaixo está uma consulta de exemplo com um ID de 20 que retorna tópicos por visualizações em uma data especificada:

--[params]
-- date :viewed_at

SELECT
topic_id,
COUNT(1) AS views_for_date
FROM topic_views
WHERE viewed_at = :viewed_at
GROUP BY topic_id
ORDER BY views_for_date DESC

Esta consulta pode ser executada a partir de um terminal com:

curl -X POST "https://your-site-url/admin/plugins/explorer/queries/20/run" \
-H "Content-Type: multipart/form-data;" \
-H "Api-Key: <api-key>" \
-H "Api-Username: system" \
-F 'params={"viewed_at":"2019-06-10"}'

Note que você precisará substituir <api-key> e <your-site-url> pela sua chave de API e domínio.

Lidando com grandes conjuntos de dados

O plugin Data Explorer limita os resultados a 1000 linhas por padrão. Para paginar através de conjuntos de dados maiores, você pode usar a consulta de exemplo abaixo:

--[params]
-- integer :limit = 100
-- integer :page = 0
SELECT * 
FROM generate_series(1, 10000)
OFFSET :page * :limit 
LIMIT :limit

Para buscar os resultados página por página, incremente o parâmetro page na solicitação:

curl -X POST "https://your-site-url/admin/plugins/explorer/queries/27/run" \
-H "Content-Type: multipart/form-data;" \
-H "Api-Key: <api-key>" \
-H "Api-Username: system" \
-F 'params={"page":"0"}'

Pare quando result_count for zero.

Para informações adicionais sobre como lidar com grandes conjuntos de dados, consulte: Result Limits and Exporting Queries

Removendo dados de relations dos resultados

Quando as consultas do Data Explorer são executadas através da interface do usuário, um objeto relations é adicionado aos resultados. Estes dados são usados para renderizar o usuário nos resultados da interface, mas é improvável que você precise deles ao executar consultas via API.

Para remover esses dados dos resultados, adicione um parâmetro download=true à sua solicitação:

curl -X POST "https://your-site-url/admin/plugins/explorer/queries/27/run" \
-H "Content-Type: multipart/form-data;" \
-H "Api-Key: <api-key>" \
-H "Api-Username: system" \
-F 'params={"page":"0"}' \
-F "download=true"

Autenticação da API

Detalhes sobre como gerar uma chave de API para as solicitações podem ser encontrados aqui: Create and configure an API key .

Se a chave de API for usada apenas para executar consultas do Data Explorer, você pode selecionar “Granular” no menu suspenso de Escopo (Scope) e, em seguida, selecionar o escopo “run queries”.

FAQs

Existe algum endpoint de api que eu possa usar para obter a lista de relatórios e os números de ID? Eu quero criar um menu suspenso com a lista nele?

Sim, você pode fazer uma solicitação GET autenticada para /admin/plugins/explorer/queries.json para obter uma lista de todas as consultas no site.

É possível criar consultas através da api?

Sim. A documentação sobre como fazer isso está em Create a Data Explorer query using the API

É possível enviar parâmetros com a solicitação post?

Sim, inclua parâmetros SQL usando a opção -F, como mostrado nos exemplos.

A exportação CSV para consultas é suportada pela API?

Embora a saída JSON seja o padrão, você pode converter manualmente os resultados para CSV. A exportação CSV nativa não é mais suportada.

Recursos adicionais

39 curtidas
Watching API
"DataExplorer::ValidationError: Missing parameter end_date of type string
Get total list of topics and their view counts from Discourse API
Best API for All First Posts in a Category
Category API request downloads all topics
Reports by Discourse
TimeStamp of Tag
How can I get the list of Discourse Topic IDs dynamically
Passing params to Data Explorer using API requires enclosing a value
Get Latest topic for Current user
Getting recently updated posts using the REST API
`DataExplorer::ValidationError: Missing parameter` when running Data Explorer queries with [params] via API
`DataExplorer::ValidationError: Missing parameter` when running Data Explorer queries with [params] via API
Backend data retrieve for analytics
Discourse-user-notes API
Admin dashboard report reference guide
How to query the topics_with_no_response.json API with filters
Use API to get topics for a period using js
Access Discourse database with n8n
Why getUserById doesn't return the user's email?
Grant a custom badge through the API
Is there an API endpoint for recently edited posts
How to query gamification score via the API?
1.5X cheers on specific TL's or groups
Page Publishing
Identifying users in multiple groups using AND rather than OR?
Validation error even when parameter passed while running data explorer API with Curl
How to change the response default_limit in data explorer?
How to change the response default_limit in data explorer?
Order/Filter searched topics by latest update to First Post
API Filter users by emails, including secondary emails
Ability to have granular scope for data explorer?
Daily, weekly, or total stats by user over a specified time range
Looking for help posting automating data explorer reports to my forum
How to get all topics from a specific category using offset/page param in the API query?
Discourse 有哪个接口能直接获取某个帖子的最后一条评论信息
想得到活跃的用户——通过api
API endpoint to create invite links has moved to /invites.json
How to get a password from database?
Can I send an external URL to the Discourse API for it to return topics linking to that URL?
How to fetch posts/topics by multiple usernames
Restrict moderator access to only the stats panel on the admin dashboard?
How to get all the deleted posts for a specific topic
Discourse forum traffic query data
Download a user's posting history via Discourse API?
Discourse Data Explorer Query Response to Slack
Filter topics in category containing file attachments
Discord Integration with Webhooks
Download result of queries into Google Spreadsheet
Who's online "API"?
Is there any endpoint that would provide a user's external account IDs from their Discourse ID?
API post request without an Accept header returns 406
Best way to get (via API) a list of users from a group, and their bios
Create a Data Explorer query using the API
How to get a full list of badges of all users
API rate limits

Este comentário parece implicar que você pode fazer exportação CSV da API. Isso é possível? Só estou curioso porque preciso dos dados como CSV. Sempre posso obtê-los como JSON e converter para CSV, mas se houver uma maneira integrada de obter CSV, seria um pouco mais fácil.

É possível fazer uma consulta ‘como criado ou atualizado nos últimos 50 segundos’?

:robot: A IA diz

-- [params]
-- int :seconds = 50

SELECT
    p.id AS post_id,
    p.created_at,
    p.updated_at,
    p.raw AS post_content,
    p.user_id,
    t.title AS topic_title,
    t.id AS topic_id
FROM posts p
INNER JOIN topics t ON t.id = p.topic_id
WHERE
    (EXTRACT(EPOCH FROM (NOW() - p.created_at)) <= :seconds
    OR EXTRACT(EPOCH FROM (NOW() - p.updated_at)) <= :seconds)
    AND p.deleted_at IS NULL
    AND t.deleted_at IS NULL
ORDER BY p.created_at DESC
LIMIT 50

Fiz um teste rápido, parece que funciona :slight_smile:

1 curtida

Não vejo o “like :heart:” que adicionei a uma postagem usando sua consulta.

Acho que você precisa usar post_actions

--[params]
--string :timespan = 50 seconds

SELECT post_id,
       user_id,
       created_at,
       updated_at,
       deleted_at
FROM  post_actions
WHERE post_action_type_id=2 AND updated_at > NOW() - INTERVAL :timespan

Versão com resultados mais bonitos

--[params]
--string :timespan = 50 seconds
--boolean :include_in_timespan_deleted = false

SELECT
  post_id,
  user_id,
  CASE
    WHEN EXTRACT(EPOCH FROM (NOW() - created_at)) < 60 THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - created_at))), ' seconds ago')
    WHEN EXTRACT(EPOCH FROM (NOW() - created_at)) < 3600 THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - created_at)) / 60), ' minutes ago')
    WHEN EXTRACT(EPOCH FROM (NOW() - created_at)) < 86400 THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - created_at)) / 3600), ' hours ago')
    ELSE CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - created_at)) / 86400), ' days ago')
  END AS relative_created_at,
  CASE
    WHEN EXTRACT(EPOCH FROM (NOW() - updated_at)) < 60 THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - updated_at))), ' seconds ago')
    WHEN EXTRACT(EPOCH FROM (NOW() - updated_at)) < 3600 THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - updated_at)) / 60), ' minutes ago')
    WHEN EXTRACT(EPOCH FROM (NOW() - updated_at)) < 86400 THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - updated_at)) / 3600), ' hours ago')
    ELSE CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - updated_at)) / 86400), ' days ago')
  END AS relative_updated_at,
  CASE
    WHEN deleted_at IS NULL THEN 'no'
    WHEN EXTRACT(EPOCH FROM (NOW() - deleted_at)) < 60 THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - deleted_at))), ' seconds ago')
    WHEN EXTRACT(EPOCH FROM (NOW() - deleted_at)) < 3600 THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - deleted_at)) / 60), ' minutes ago')
    WHEN EXTRACT(EPOCH FROM (NOW() - deleted_at)) < 86400 THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - deleted_at)) / 3600), ' hours ago')
    ELSE CONCAT(ROUND(EXTRACT(EPOCH FROM (NOW() - deleted_at)) / 86400), ' days ago')
  END AS relative_deleted_at
FROM
  post_actions
WHERE
  post_action_type_id = 2
  AND updated_at > NOW() - INTERVAL :timespan
  AND (
    :include_in_timespan_deleted = false
    OR (deleted_at IS NOT NULL AND deleted_at > NOW() - INTERVAL :timespan)
  )

2 curtidas

Oooh, eu li errado! Eu li a frase como "É possível fazer uma consulta como ‘criado ou atualizado nos últimos 50 segundos’?

(note a posição da aspa simples)"

1 curtida

Obrigado a todos,

Postei aqui porque foi para onde o ask.discourse me direcionou.
O que estou procurando é se a API está fornecendo essa capacidade.

1 curtida

Sim, claro.

Você cria a consulta no explorador de dados, em seguida, executa a consulta através da API, conforme descrito neste guia.

Acabei de executar a consulta de Moin através da API e ela retornou corretamente os resultados esperados.

4 curtidas

Eu também estava me perguntando sobre isso. JSON é a única forma de exportar dados via API ou a exportação CSV também é suportada para o Data Explorer?

Obrigado a todos,

Desculpe pela resposta tardia - estive offline por um tempo.

O que estou fazendo atualmente é pesquisar todos os tópicos/postagens criados hoje e filtrar os tópicos/postagens atualizados antes do carimbo de data/hora.

1 curtida

Se você não quiser “colocar a mão na massa”, pode perguntar ao bot em ask.discourse.com. Ele geralmente é bem preciso em relação a consultas SQL relacionadas ao Discourse (mas não assuma que está certo, verifique o código para ter certeza).

1 curtida

O cabeçalho Content-Type está correto?
Nas ferramentas do desenvolvedor, ao inspecionar uma consulta do Data Explorer com parâmetros, o cabeçalho Content-Type aparece como:

Content-Type: application/x-www-form-urlencoded; charset=UTF-8

No entanto, o comando cURL atual inclui:

-H "Content-Type: multipart/form-data;"


1 curtida
  • multipart/form-data
  • application/x-www-form-urlencoded
  • application/json

são todos content-types válidos que você pode usar ao fazer uma requisição de API.

1 curtida

@blake
linguagem python
biblioteca requests
Você poderia fornecer uma consulta de exemplo da API Data Explorer que inclua três parâmetros
consulte Tópico que diz que os parâmetros precisam estar estritamente entre aspas duplas

Claro, aqui está um exemplo usando python:

import json
import requests

API_KEY      = "SUA_API_KEY"
API_USERNAME = "system"
QUERY_ID     = 20
SITE_URL     = "https://seu-site-url"

# todos os valores devem ser strings
params = {
    "user_id":   "2",
    "viewed_at": "2019-06-10",
    "limit":     "5"
}

# O Data Explorer espera os parâmetros como uma string codificada em JSON
payload = {
    "params": json.dumps(params)
}

url = f"{SITE_URL}/admin/plugins/explorer/queries/{QUERY_ID}/run"
headers = {
    "Api-Key":       API_KEY,
    "Api-Username":  API_USERNAME,
    "Content-Type":  "application/json"
}

r = requests.post(url, headers=headers, json=payload)
r.raise_for_status()
print(r.json())
3 curtidas