ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Read the Docs 服务端搜索(Server Side Search)完全指南:Elasticsearch 驱动的全站全文搜索、查询语法与 API 集成

Read the Docs 服务端搜索(Server Side Search)完全指南:Elasticsearch 驱动的全站全文搜索、查询语法与 API 集成 后端文档【免费下载链接】readthedocs.orgThe source code that powers readthedocs.org项目地址https://gitcode.com/gh_mirrors/re/readthedocs.org点击查看免费下载Read the Docs即本仓库 readthedocs.org 所驱动的平台为所有项目的所有页面提供基于 Elasticsearch 的全站全文搜索能力即Server Side Search服务端搜索。它取代了各文档构建工具自带的客户端搜索让搜索结果精确落到每个标题heading锚点并支持跨项目、跨子项目检索、自定义排名、特殊查询语法与完整 REST API。本文基于 docs/user/server-side-search/index.rst 及其姊妹文档 语法说明、API 参考 展开并结合仓库源码readthedocs/search/目录深入讲解底层实现帮助读者掌握从搜索特性、查询语法、API 调用到配置调优的完整实战方案。一、什么是服务端搜索Read the Docs 的搜索被称为服务端搜索Server Side Search因为它由 Read the Docs 平台在服务端完成文档构建完成后平台解析生成的 HTML 页面并写入 Elasticsearch 索引用户搜索时请求直接打到平台提供的搜索 API / 搜索界面而不是在浏览器里用 JavaScript 遍历文档自带的静态索引文件。这一设计带来几个关键优势覆盖全部项目与版本所有项目的所有公开页面都被索引搜索范围不再局限于当前阅读的文档。按标题精确命中平台索引页面中的每个标题heading因此搜索结果可以精确到文档中的具体小节并带有可跳转的锚点。统一体验无论底层是 Sphinx、MkDocs 还是其他构建工具搜索界面与交互保持一致。在仓库中搜索功能由readthedocs/search/模块承载索引文档定义在 readthedocs/search/documents.pyElasticsearch 查询构造在 readthedocs/search/faceted_search.pyHTML 解析在 readthedocs/search/parsers.pyAPI 视图在readthedocs/search/api/下。Elasticsearch 连接配置位于 readthedocs/settings/base.py默认通过ELASTICSEARCH_DSL指向search:9200服务page_index索引默认 1 个分片、1 个副本并关闭了ELASTICSEARCH_DSL_AUTO_REFRESH以提升索引写入性能。二、核心搜索特性1. 跨子项目搜索Read the Docs 的子项目Subprojects机制允许把多个独立项目托管在同一个域名下。服务端搜索默认把主项目同域名下的所有子项目一并纳入主项目的搜索结果。在 API v2 的旧实现中这一行为写死在视图逻辑里readthedocs/search/api/v2/views.py 会遍历Project.objects.filter(superprojects__parent_id...)把每个子项目加入搜索集合子项目若不存在同名版本则回退到其默认版本。提示在 API v3 中搜索主项目时不会自动包含子项目结果如需包含需显式使用subprojects:参数详见下文查询语法章节。2. 搜索结果精确落到目标内容平台会索引文档中的每个标题所以搜索结果可以精确到标题所在的小节并附带id锚点供直接跳转。这一能力来自索引结构PageDocument中除页面标题title外还有sections嵌套字段包含每个小节的id、title与contentreadthedocs/search/documents.py小节内容还启用了with_positions_offsets词向量以加速大文档的高亮。解析时readthedocs/search/parsers.py 的_parse_sections会把每个小节含子小节组织成结构化对象把标题之下、下一个标题之前的内容归入该小节。3. 完全控制结果排序自定义排名平台允许通过配置文件为每个页面设置自定义排名rank用于让用户始终先看到相关内容、或让旧内容自然下沉。配置项为search.ranking在项目根目录的.readthedocs.yaml配置文件中设置详见配置文件 v2 参考version: 2 search: ranking: api/v1/*: -1 api/v2/*: 4 ignore: - 404.htmlsearch.ranking的类型是模式到排名的映射默认{}模式匹配的是构建产物 HTML 的相对路径例如应写index.html而不是docs/index.rst或/en/latest/index.html模式支持通配符*匹配一切含斜杠、?匹配任意单个字符、[seq]匹配seq中的任意字符排名取值范围为-10 到 10含端点越接近 -10 结果越靠后越接近 10 结果越靠前0表示正常排名而不是无排名若多个模式同时命中同一页面最后一个匹配的模式生效实践建议优先降低要废弃页面的排名而不是抬高其他所有页面的排名。对应的search.ignore用于把匹配的页面彻底排除出搜索索引类型为模式列表默认值为[search.html, search/index.html, 404.html, 404/index.html]。这些配置在构建时由 readthedocs/projects/tasks/search.py 落实process()中先用search_ignore的模式fnmatch过滤掉被忽略的页面再按倒序遍历search_ranking让最后一个匹配生效第 79-82 行最后把页面按每 100 个一批写入索引。排名在查询阶段的实现位于 readthedocs/search/faceted_search.pyPageSearch.query使用 Elasticsearch 的FunctionScore查询通过脚本把用户设置的rank-1010共 21 个取值映射为权重系数[0.01, 0.05, ..., 1, 1.3, ..., 2]再乘上原始相关性分数。映射表的设计保证最低档 0.8 能把sections.title^2的最高分拉低到接近title^1.5最高档 1.3 能把最低分抬高到接近最高分——确保精确命中始终优先于排名靠前的页面。4. 跨你有权限的项目搜索在 Dashboard 中可以一次性搜索所有你有权限访问的项目不必再为记不清文档在哪个项目里发愁。这对应查询参数user:me例如user:me test在源码中SearchExecutor._get_projects_from_user通过Project.objects.for_user(userrequest.user)枚举当前用户有权限的项目并为每个项目取默认版本进行检索readthedocs/search/api/v3/executor.py。5. 特殊查询语法平台支持完整的查询语法包括精确短语、前缀、模糊匹配等详见下文查询语法章节。6. 可配置搜索行为可以通过两种途径配置配置文件通过.readthedocs.yaml中的search段配置排名与忽略列表项目设置界面在项目 Dashboard 的Settings→ 左侧栏Search中可开关两个选项Enable search modal控制文档页面中是否展示 Read the Docs 搜索弹窗Show subprojects filter in search modal控制读者是否可以在搜索弹窗内按子项目过滤结果。这两个开关对应Project.addons模型上的字段readthedocs/projects/models.pysearch_enabled默认True与search_show_subprojects_filter默认True另有search_default_filter用于设定默认过滤条件。7. 开箱即用平台会覆盖 Sphinx 项目默认的搜索使上述能力自动生效若服务端搜索没有返回任何结果会自动回退到项目内置搜索避免遗漏。8. API搜索能力完全可以通过 API 集成详见下文API章节。9. 分析Analytics平台会记录用户的搜索行为帮助了解用户正在搜索什么详见搜索分析文档。每次搜索请求都会在 readthedocs/search/api/v3/views.py 的_record_query中被异步记录通过tasks.record_search_query_batch.delay包含查询词、涉及的项目/版本列表与结果总数。三、搜索查询语法1. 参数Parameters参数形式为name:value可以出现在查询语句的任意位置除user外project与subprojects均可重复出现多次。除参数外的其他文本都会作为搜索内容。如果不想让某个词被解析为参数可以用反斜杠转义例如project\:docs。未知参数如foo:bar不会被当作参数无需转义。参数作用示例project指定要搜索的项目与版本不含子项目与翻译。未指定版本时使用该项目默认版本可重复出现project:docs test、project:docs/latest test、project:docs/stable project:dev testsubprojects搜索指定项目及其所有子项目。未指定版本时各项目均用默认版本指定版本时拥有该版本的子项目用该版本没有的则回退默认版本可重复出现subprojects:docs test、subprojects:docs/latest test、subprojects:docs/stable subprojects:dev testuser搜索当前用户me有权限访问的项目仅支持me且只能出现一次重复时后者覆盖前者user:me test参数解析由SearchQueryParser实现readthedocs/search/api/v3/queryparser.py它按空白拆分查询串把形如name:value且name在allowed_argumentsproject/subprojects为列表型user为字符串型中的片段识别为参数其余为普通文本转义后的\:会被还原为:。项目与版本通过{project}/{version}形式拆分_split_project_and_versionreadthedocs/search/api/v3/executor.py未提供版本时自动使用项目的默认版本。权限Permissions若用户对某个版本没有权限或该版本不存在则该版本不会出现在结果中。API 响应会返回最终搜索实际使用的所有项目便于前端展示本次搜索覆盖了哪些项目。限制Limitations单次搜索最多涉及100 个项目超出部分会被忽略该语法仅在使用API v3或全局搜索https://app.readthedocs.org/search/时可用同一项目搜索多个版本不受支持后出现的版本会覆盖之前的版本。在源码中100 项目上限由SearchExecutor的max_projects100实现projects属性用islice(..., self.max_projects)截断并用 dict 保证每个项目只保留一个版本readthedocs/search/api/v3/executor.py。2. 特殊查询Special QueriesRead the Docs 使用 Elasticsearch 的Simple Query String查询查询越复杂结果越精确。对应源码在 readthedocs/search/faceted_search.py文本查询同时以and与or两种默认操作符构造查询and命中的得分更高并为模糊匹配设置了fuzzy_prefix_length1、fuzzy_max_expansions15以避免复杂查询超时。支持的语法精确短语用双引号包裹只返回短语完全匹配的结果。例如custom css、adding a subproject、when a 404 is returned。前缀查询词尾加*返回包含该前缀词的结果。例如test*、build*。模糊匹配Fuzziness词后加~N表示编辑距离适合拼写不确定的场景。例如doks~1、test~2、getter~2。词距接近Proximity短语后加~N匹配彼此接近的词。例如dashboard admin~2、single documentation~1、read the docs policy~5。值得说明的是查询是否按高级语法处理并非只看长度_is_advanced_query会检测查询中是否含、|、-、、*、(、)、~等 Simple Query String 特殊符号readthedocs/search/faceted_search.py。此外当查询为单个词且未使用高级语法时在DEFAULT_TO_FUZZY_SEARCH特性开关下会走模糊 通配符Wildcard词尾补*查询以支持部分词与子串匹配第 126-155 行。四、搜索 API1. API v3推荐端点GET /api/v3/search/返回指定项目或项目子集的搜索结果列表结果按小节section切分并带有命中词高亮。请求参数参数说明q搜索查询词语法见上文也支持project:、subprojects:、user:参数page跳转到指定页page_size每页结果数默认 50响应字段字段说明type结果类型目前只有pageproject项目对象含slug与aliasversion版本对象含slugtitle页面标题domain结果页面的规范域名path结果页面路径highlights含命中词子串的对象文本为 HTML 转义后的内容命中词包在span标签内blocks页面内的结果块列表当前仅section类型带id锚点的页面小节⚠️安全警告除highlights外响应中其他内容不会做 HTML 转义集成方在把内容渲染进页面之前必须自行转义以防 XSS。示例请求bashcurl https://app.readthedocs.org/api/v3/search/?qproject:docs%20server%20side%20search示例请求Pythonimport requests URL https://app.readthedocs.org/api/v3/search/ params { q: project:docs server side search, } response requests.get(URL, paramsparams) print(response.json())示例响应{ count: 41, next: https://app.readthedocs.org/api/v3/search/?page2qproject:docs%20serversidesearch, previous: null, projects: [ {slug: docs, versions: [{slug: latest}]} ], query: server side search, results: [ { type: page, project: {slug: docs, alias: null}, version: {slug: latest}, title: Server Side Search, domain: https://docs.readthedocs.io, path: /en/latest/server-side-search.html, highlights: { title: [spanServer/span spanSide/span spanSearch/span] }, blocks: [ { type: section, id: server-side-search, title: Server Side Search, content: Read the Docs provides full-text search across all of the pages of all projects, this is powered by Elasticsearch., highlights: { title: [spanServer/span spanSide/span spanSearch/span], content: [You can spansearch/span all projects at https:#x2F;#x2F;readthedocs.org#x2F;spansearch/span#x2F] } }, { type: domain, role: http:get, name: /_/api/v2/search/, id: get--_-api-v2-search-, content: Retrieve search results for docs, highlights: { name: [], content: [Retrieve spansearch/span results for docs] } } ] } ] }v3 的视图实现在 readthedocs/search/api/v3/views.pySearchAPI要求q参数必填_validate_query_params匿名与登录用户分别使用SearchAnonRateThrottle/SearchUserRateThrottle限流为100 次/分钟RATE_LIMIT 100/minute。响应顶层的projects与query字段由_add_extra_fields在序列化后补充projects列出最终参与搜索的项目与版本query为去除参数后的实际查询词readthedocs/search/api/v3/views.py。此外v3 响应会通过_add_cache_tags为所有参与搜索的项目打上Cache-Tag项目 slug、{project}/{version}与rtd-search标签使 CDN 能在文档更新或索引重建rtd-search后精确失效缓存为避免超出 CDN/nginx 头部大小限制标签总量被限制在 2000 字符内第 124-157 行。项目/版本在响应中成为对象v3 的PageSearchSerializer将project序列化为{slug, alias}、version序列化为{slug}并移除project_alias字段readthedocs/search/api/v3/serializers.py。2. 从 API v2 迁移v2 用独立查询参数指定项目与版本v3 改为在查询词内声明。迁移映射关系如下v2 参数v3 写法project: docs、version: latest、q: testq: project:docs/latest testv3 响应与 v2 非常相似主要变化project由字符串变为对象version由字符串变为对象不再有project_alias字段已并入project对象。另一个关键行为差异在 v3 中搜索父项目不会自动包含子项目结果需要显式传入subprojects参数。3. 认证与授权如果项目使用私有版本Private versions用户只能搜索自己有权限的项目。认证授权基于当前会话或任何有效的分享方式sharing可通过/api/v3/projects/project_slug/sharing/以编程方式创建与撤销分享见 API v3 文档。要使用当前用户会话必须从文档所服务的域名调用 API即you-docs-domain/_/api/v3/search/。例如项目https://docs.readthedocs-hosted.com/对应的搜索端点为https://docs.readthedocs-hosted.com/_/api/v3/search/。在开源版实现中权限检查由SearchExecutor._has_permission与_get_project_version内部版本管理器 public()过滤 隐藏版本控制共同完成readthedocs/search/api/v3/executor.py商业版.com会覆写权限逻辑以接入其认证后端。4. API v2已废弃⚠️ 请优先使用 API v3迁移说明见上文。v2 端点仍可使用但已废弃。端点GET /api/v2/search/返回某项目含其子项目的搜索结果。请求参数q查询词、project项目 slug、version版本 slug、page、page_size默认 50。响应字段与 v3 基本一致但project、version、project_alias均为字符串project_alias在结果为子项目时表示其别名。示例请求bashcurl https://app.readthedocs.org/api/v2/search/?projectdocsversionlatestqserver%20side%20search示例请求Pythonimport requests URL https://app.readthedocs.org/api/v2/search/ params { q: server side search, project: docs, version: latest, } response requests.get(URL, paramsparams) print(response.json())示例响应{ count: 41, next: https://app.readthedocs.org/api/v2/search/?page2projectread-the-docsqserversidesearchversionlatest, previous: null, results: [ { type: page, project: docs, project_alias: null, version: latest, title: Server Side Search, domain: https://docs.readthedocs.io, path: /en/latest/server-side-search.html, highlights: { title: [spanServer/span spanSide/span spanSearch/span] }, blocks: [ { type: section, id: server-side-search, title: Server Side Search, content: Read the Docs provides full-text search across all of the pages of all projects, this is powered by Elasticsearch., highlights: { title: [spanServer/span spanSide/span spanSearch/span], content: [You can spansearch/span all projects at https:#x2F;#x2F;readthedocs.org#x2F;spansearch/span#x2F] } } ] } ] }v2 视图要求q、project、version三个参数全部必填readthedocs/search/api/v2/views.py权限校验使用IsAuthorizedToViewVersion并自动把子项目并入搜索范围。关于商业版Read the Docs for Business若使用app.readthedocs.com上述所有示例 URL 中的https://app.readthedocs.org/需替换为https://app.readthedocs.com/使用私有版本时还需检查上文认证与授权小节。五、边输入边搜索Search as you type搜索弹窗支持边输入边搜索as-you-type用户在输入过程中即可看到候选结果快速定位目标内容同时会保存最近搜索记录便于日后回看。在文档页面按/正斜杠即可唤起搜索弹窗并开始输入。六、配置搜索搜索选项可在项目Dashboard中配置进入 Dashboard点击项目名称进入Settings在左侧栏选择Search。在该页面可以切换Enable search modal启用搜索弹窗控制文档中是否展示 Read the Docs 搜索弹窗Show subprojects filter in search modal在搜索弹窗中显示子项目过滤器控制读者能否按子项目过滤搜索结果。对应的数据库字段Project.addons定义在 readthedocs/projects/models.py默认均为开启。项目级的search_indexing_enabled第 587 行附近则控制该项目是否参与搜索索引PageDocument.get_queryset会过滤掉未开启索引、被标记 ignore、delisted除名或 spam 的项目与页面readthedocs/search/documents.py。除此之外还可以通过.readthedocs.yaml的search段做更细粒度的内容级控制排名与忽略完整 schema 与示例见配置文件 v2 参考。七、主内容Main Content如何被识别服务端搜索只索引 HTML 页面的主内容区域忽略页头、页脚、导航等与文档内容无关的元素从而保证结果聚焦并避免导航菜单等重复元素污染相关性。主内容节点的识别顺序如下优先级从高到低带rolemain属性的元素ARIA 角色被众多静态站点生成器与主题使用mainHTML5 标签首个h1标签的父节点假定所有小节是兄弟节点、共用一个父容器body标签兜底。这一逻辑在解析器中与文档完全对应readthedocs/search/parsers.py 的_get_main_node实现顺序为css_first([rolemain])→css_first(main)→ 首个h1的容器父节点 →body。细节上还有一个巧妙的处理若h1的父标签是header会先返回header标签作为标题容器_get_header_container再取其父节点以兼容主题中标题被包在 header 里的结构。完整说明含 HTML 结构示例与检测优化建议见主内容检测参考。概括要点为提升识别准确率同时改善无障碍体验建议在主题主内容容器上加rolemain、使用main标签、并确保主内容区有至少一个h1标题若自动检测失败可在项目Settings→Addons→Advanced中填写CSS main content selector例如div#main或.my-content留空则使用自动检测。注意该自定义选择器目前只影响 Visual Diff 与 Link Previews视觉差异、链接预览不影响搜索索引避免使用body这类过于宽泛、或匹配多个节点的选择器。八、索引与排序原理源码视角1. 索引文档结构页面索引文档PageDocumentreadthedocs/search/documents.py包含元数据project、version、doctype文档类型、path、full_path、rank用户自定义排名可搜索内容title、嵌套的sections每节含id、title、content文本字段采用simple分析器按非字母字符切分如python.submodule会被切为[python, submodule]sections.content启用with_positions_offsets词向量以加速高亮prepare_rank会校验排名是否在 -1010 之间超出则归零查询集过滤掉未开启索引、ignore、delisted、spam 的内容。2. 查询构造与字段加权PageSearchreadthedocs/search/faceted_search.py对两类字段分别构造查询外层字段_outer_fields [title^1.5]嵌套小节字段_section_fields [sections.title^2, sections.content]通过Nested查询并限制inner_hits大小为 3即每页最多返回 3 个命中小节。之后用Bool(should...)组合再用FunctionScore脚本把rank映射为分数权重见上文自定义排名小节最终让相关性分数与用户排名共同决定结果顺序。3. 搜索分析与数据记录每次 API 搜索都会被异步记录tasks.record_search_query_batch.delay这些数据正是搜索分析报表的来源使项目维护者可以了解用户的搜索意图、并据此优化文档结构或排名配置。九、使用建议与最佳实践优先使用 API v3新集成请直接使用/api/v3/search/将项目、版本约束写进q参数project:slug/version、subprojects:slug、user:me并善用响应中的projects与query字段做前端展示。集成时务必自行转义除highlights外的响应内容未经 HTML 转义渲染前需自行转义以防 XSS。合理利用排名而非删除想弱化旧内容时优先降低search.ranking而非删除页面想彻底隐藏页面再用search.ignore。注意搜索范围差异v3 中父项目搜索默认不含子项目子项目搜索需用subprojects:参数并留意版本缺失时回退默认版本的规则。主内容检测遵循 ARIA 约定为你的主题添加rolemain或main既能提升搜索索引的准确性也能改善站点可访问性。通过上述特性、语法、API 与配置的组合无论是普通项目维护者还是需要深度集成搜索能力的开发者都能在 Read the Docs 上构建出精确、可控、可分析的全站搜索体验。赞分享后端文档【免费下载链接】readthedocs.orgThe source code that powers readthedocs.org项目地址https://gitcode.com/gh_mirrors/re/readthedocs.org点击查看免费下载相关推荐Read the Docs 服务端搜索查询语法完整指南参数过滤、转义规则与 Elasticsearch 高级检索Read the Docs 服务端搜索查询语法完整指南参数过滤、转义规则与 Elasticsearch 高级检索 服务端搜索Server Side Sear后端文档Read the Docs 服务端搜索深度解析Elasticsearch 索引、重建与查询的完整机制Read the Docs 服务端搜索深度解析Elasticsearch 索引、重建与查询的完整机制 Read the Docs 使用 Elasticsear后端文档ToolJet Table 组件服务端搜索Server Side Search完整指南从 SQL 查询到事件链路ToolJet Table 组件服务端搜索Server Side Search完整指南从 SQL 查询到事件链路 本篇指南讲解如何在 ToolJet 的低代码后端前端AI 应用MCP 服务上一篇LEGION_Y7000Series_Hackintosh 4K屏幕升级指南让你的拯救者笔记本完美支持4K显示下一篇如何使用dnSpy进行代码混淆强度评估完整量化分析指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表