使用 Discourse API 运行 Data Explorer 查询

:bookmark: 本指南介绍如何使用 Discourse API 来创建、运行和管理 Data Explorer 插件的查询。

:person_raising_hand: 所需用户级别:管理员

通过 Discourse API 几乎可以触发任何可以通过 Discourse 用户界面执行的操作。

本文档提供了专门与 Data Explorer 插件结合使用 API 的全面概述。

有关如何查找执行操作的正确 API 请求的常规概述,请参阅:Reverse engineer the Discourse API

运行 Data Explorer 查询

要通过 API 运行 Data Explorer 查询,请向 /admin/plugins/explorer/queries/<query-id>/run 发出 POST 请求。您可以通过在您的 Discourse 站点上访问该查询并在地址栏中查看 id 参数来找到查询 ID。

下面是一个 ID 为 20 的示例查询,它返回指定日期的按浏览量排序的主题:

--[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

可以使用以下命令从终端运行此查询:

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"}'

请注意,您需要将 <api-key><your-site-url> 替换为您的 API 密钥和域名。

处理大型数据集

Data Explorer 插件默认将结果限制为 1000 行。要分页浏览更大的数据集,您可以使用下面的示例查询:

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

要逐页获取结果,请在请求中递增 page 参数:

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"}'

result_count 为零时停止。

有关处理大型数据集的更多信息,请参阅:Result Limits and Exporting Queries

从结果中移除 relations 数据

Data Explorer 查询通过用户界面运行时,结果中会添加一个 relations 对象。此数据用于在 UI 结果中渲染用户,但在通过 API 运行查询时您不太可能需要它。

要从结果中删除该数据,请在请求中添加 download=true 参数:

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"

API 身份验证

有关生成用于请求的 API 密钥的详细信息,请参阅:Create and configure an API key

如果 API 密钥仅用于运行 Data Explorer 查询,您可以从“Scope”(范围)下拉菜单中选择“Granular”(粒度),然后选择“run queries”(运行查询)范围。

常见问题解答

我可以使用任何 api 端点来获取报告列表和 ID 编号吗?我想在其中构建一个下拉列表?

是的,您可以向 /admin/plugins/explorer/queries.json 发出经过身份验证的 GET 请求,以获取站点上所有查询的列表。

是否可以通过 api 创建查询?

是的。有关如何执行此操作的文档位于 Create a Data Explorer query using the API

是否可以将参数与 post 请求一起发送?

是的,使用 -F 选项包含 SQL 参数,如示例所示。

API 是否支持查询的 CSV 导出?

虽然 JSON 输出是标准的,但您可以手动将结果转换为 CSV。原生 CSV 导出不再受支持。

附加资源

39 个赞
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

这条评论似乎暗示可以从 API 进行 CSV 导出。有可能吗?只是好奇,因为我需要 CSV 格式的数据。我可以随时获取 JSON 格式并转换为 CSV,但如果有一种内置的 CSV 获取方式会更简单一些。

是否可以进行“在过去50秒内创建或更新”的查询?

:robot: AI说

-- [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

快速测试了一下,似乎有效 :slight_smile:

1 个赞

我没有看到您使用查询添加的“喜欢 :heart:”。
我认为您需要使用 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

结果更美观的版本

--[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 个赞

哦,我读错了!我把这句话读成了“是否可以进行类似‘创建或更新在过去 50 秒内’的查询?”
(注意单引号的位置)

1 个赞

谢谢大家,

我在这里发帖是因为 ask.discourse 指引我来的。
我想知道 API 是否提供了此功能。

1 个赞

是的,当然。

您在数据资源管理器中创建查询,然后按照本指南中的说明通过 API 运行查询。

我刚刚通过 API 运行了 Moin 的查询,它正确返回了预期的结果。

4 个赞

我也想知道这个问题。通过 API 导出数据是否只有 JSON 这一种方式,还是数据浏览器也支持 CSV 导出?

谢谢大家,

抱歉回复晚了——我暂时离线了一会儿。

我目前正在搜索今天创建的所有主题/帖子,并过滤掉在时间戳之前更新的主题/帖子。

1 个赞

如果你不想亲自动手,可以向 ask.discourse.com 上的机器人提问。它通常在与 Discourse 相关的 SQL 查询方面相当准确(但不要假设它是正确的,请务必检查代码以确保)。

1 个赞

Content-Type 标头是否正确?
在开发者工具中检查带有参数的数据浏览器查询时,Content-Type 标头显示为:

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

但是,当前的 cURL 命令包含:

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


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

在发起 API 请求时,以上都是有效的内容类型(content-types)。

1 个赞

@blake
language python
library requests
您能否提供一个包含三个参数的 API 示例 Data Explorer 查询
refer [Topic]( Passing params to Data Explorer using API requires enclosing a value ) 其中说明参数需要严格用双引号括起来

当然,这是一个使用 Python 的示例:

import json
import requests

API_KEY      = "YOUR_API_KEY"
API_USERNAME = "system"
QUERY_ID     = 20
SITE_URL     = "https://your-site-url"

# 所有值都必须是字符串
params = {
    "user_id":   "2",
    "viewed_at": "2019-06-10",
    "limit":     "5"
}

# Data Explorer 期望将参数作为 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 个赞