完全指南:列表查询、过滤、分页、排序与实时订阅)
Sails Find 蓝图Blueprint完全指南列表查询、过滤、分页、排序与实时订阅【免费下载链接】sailsRealtime MVC Framework for Node.js项目地址: https://gitcode.com/gh_mirrors/sa/sails本篇指南围绕 Sails 内置的Find blueprint 端点展开讲解如何通过GET /:model查询符合指定条件的记录列表并利用请求参数实现过滤含 Waterline 子属性条件修饰符、分页、排序、字段选择与关联填充populate。读完本文你将掌握 Find 蓝图的全部请求参数与行为语义理解它在 Sails 蓝图系统 中的底层实现基于 Waterlinefind()并能在 REST、shortcut、WebSocketsocket三种触发方式下正确使用它包括自动订阅subscribe / auto-watch带来的实时通知能力。Find blueprint 是什么Find blueprint 是 Sails 为每个模型自动生成的列表查询端点。只要模型中存在对应的自动路由REST 蓝图或 shortcut 蓝图就可以用一次简单的 HTTP 请求查回一组记录GET /:model例如项目中有Purchase模型则GET /purchase会返回数据库中一批购买记录。返回结果可以依据蓝图配置与请求中携带的参数进行过滤filtering、分页pagination与排序sorting。从源码角度看Sails 在 blueprints 钩子注册动作 阶段会为每个模型注册modelIdentity /find动作其实现位于 Find 蓝图动作源码核心逻辑非常简洁调用parseBlueprintOptions(req)把请求解析为一组 Waterline 查询选项criteria、populates、meta执行Model.find(criteria, populates).meta(meta)调用底层 ORM若为 socket 请求则执行订阅逻辑最终通过res.ok()返回记录数组。该端点如何被路由绑定GET /:model形式的 Find 端点来自两种自动路由机制默认均开启见 sails.config.blueprints路由类型配置项默认值生成的 URL 模式REST 蓝图rest: trueget /:model例如GET /purchaseShortcut 蓝图shortcuts: trueget /:model/find例如GET /purchase/find绑定逻辑位于 bindShadowRoutesREST 路由调用_bindRestRoute(get %s, find)shortcut 路由调用_bindShortcutRoute(get %s/find, find)。此外即使自动路由被关闭你也可以在 自定义路由 中把任意 URL 显式指向该蓝图动作如GET /api/purchases: purchase/find。请求参数详解Find blueprint 支持以下请求参数全部为可选项参数类型说明model((string))目标模型的 identity。例如GET /purchase中的purchase。_*_((string?))以模型属性同名的查询参数进行属性过滤。例如Purchase模型有amount属性GET /purchase?amount99.99将返回金额为 $99.99 的购买记录列表。where((string?))不按单属性过滤而是直接给出 Waterline 查询语言 中 WHERE 片段以 JSON 字符串编码。借助它可以利用contains、startsWith等子属性条件修饰符编写更强大的find()查询。例如?where{name:{contains:theodore}}。limit((number?))最多返回的记录条数分页用。默认为 30。例如?limit100。skip((number?))跳过的记录条数分页用。例如?skip30。sort((string?))排序规则。默认按主键值升序返回。例如?sortlastName%20ASC。select((string?))结果中每条记录要包含的属性逗号分隔列表。默认选中全部属性。对 pluralcollection关联属性无效。例如?selectname,age。omit((string?))结果中每条记录要排除的属性逗号分隔列表。不能与select同时使用。对 pluralcollection关联属性无效。例如?omitfavoriteColor,address。populate((string))若指定覆盖默认的自动填充过程。接受逗号分隔的关联属性名列表传false表示不做任何填充。填充过程如何按模型定义的关联把值填入返回记录可参见 记录与填充值 相关说明。参数背后的解析逻辑源码级以上参数并非凭空设计它们与 parseBlueprintOptions 默认实现 中find/findOne分支的处理一一对应值得理解其边界行为where的两种形态先读取req.allParams().where若为字符串则尝试JSON.parse()解析失败会抛出UsageError最终返回 400。若未提供where则把其余未绑定参数组装为 where并剔除黑名单[limit, skip, sort, populate, select, omit]同时丢弃值为undefined的参数。select与omit互斥源码先判断select存在则设置criteria.select否则else if才处理omit因此两者同时发送时omit会被忽略两者都会按逗号拆分并trim每个属性名。limit默认值未传limit时固定为DEFAULT_LIMIT 30req.param(limit)优先。skip仅在显式提供时加入 criteria默认 0。sort支持形如lastName ASC的字符串也支持可JSON.parse的对象形式如{name: 1}若字符串不是合法 JSON 则原样解释。相同逻辑还出现在 actionUtil.parseSort。populate若值为false字符串则populates置空对象完全不填充否则按逗号拆分并去空格生成要填充的关联映射。默认情况下所有collection型关联会带上limit: 30的填充上限默认 populates 构造model型关联则无 limit。完整使用示例以下示例查找数据库中最新按创建时间倒序的至多 30 条购买记录GET /purchase?sortcreatedAt DESClimit30期望响应返回一个 JSON 数组例如[ { amount: 49.99, id: 1, createdAt: 1485551132315, updatedAt: 1485551132315 }, { amount: 99.99, id: 47, createdAt: 1485551158349, updatedAt: 1485551158349 } ]注意createdAt/updatedAt为时间戳数字默认按主键升序排列当显式传入sort后按排序规则输出。返回体由 find.js 中的res.ok(matchingRecords)统一序列化。使用 jQuery 调用$.get(/purchase?sortcreatedAt DESC, function (purchases) { console.log(purchases); });使用 sails.io.jsWebSocket 客户端调用io.socket.get(/purchase?sortcreatedAt DESC, function (purchases) { console.log(purchases); });sails.io.js的完整用法见 sails.io.js 参考文档。使用 Angular 调用$http.get(/purchase?sortcreatedAt DESC) .then(function (res) { var purchases res.data; console.log(purchases); });使用 cURL 调用curl http://localhost:1337/purchase?sortcreatedAt%20DESC在 URL 中直接书写空格是不合法的因此排序参数中的空格需要编码为%20在 cURL 示例里即为sortcreatedAt%20DESC。实时能力socket 请求的自动订阅Find blueprint 与 WebSocket 深度集成这是它区别于普通 CRUD 端点的重要特性如果该动作是通过 socket 请求触发的请求方 socket 会被订阅到所有返回的记录上。此后若这些记录中的任意一条被更新或删除一条消息会被发送到该 socket 的客户端通知它这一变更。该行为的实现位于 find.jsif (req._sails.hooks.pubsub req.isSocket) { Model.subscribe(req, _.pluck(matchingRecords, Model.primaryKey)); // 仅当 autoWatch 开启时才 ._watch() 模型以感知新建记录 if (req.options.autoWatch) { Model._watch(req); } // 同时对返回记录涉及的所有关联模型实例做深度订阅 _.each(matchingRecords, function (record) { actionUtil.subscribeDeep(req, record); }); }其语义可拆解为三点底层订阅原语定义在 pubsub 钩子 的subscribe/unsubscribe实现中订阅返回的记录对每条返回记录调用Model.subscribe(req, [pk])后续这些记录的 update/destroy 事件会推送给当前 socket。详见 Model.subscribe()。auto-watch监听新建当 sails.config.blueprints.autoWatch 为true默认值时还会对模型执行_watch()使 socket 同时收到新建记录的通知从而支持类似实时列表自动刷新的场景。深度订阅关联actionUtil.subscribeDeep()actionUtil.js会遍历模型关联对collection型关联订阅每条关联记录对model型关联若填充值是对象则订阅其对应主键。需要强调的是如果同一个 socket之后又通过io.socket.put()调用Update或Destroy蓝图默认情况下不会向该请求方 socket 自身推送消息而是推送给其他已订阅的 socket。这是刻意设计客户端 SDK 的回调负责处理服务端响应例如关闭 loading 动画而订阅消息则用于通知其他关注者详见 Blueprint API 与订阅。需要感知新建时把autoWatch设为false即可关闭对应通知。错误处理与状态码从 find.js 可以看到明确的错误分类当 Waterline 返回UsageError例如传入非法 criteria、whereJSON 解析失败时响应400 Bad Request并借助 formatUsageError 生成更友好的错误信息其他非预期错误一律返回500 Server Error。因此使用where等高级参数时务必保证 JSON 语法与属性名正确否则会得到 400 而不是静默失败。配置与自定义常用蓝图配置项在 config/blueprints.js仓库对应文档见 sails.config.blueprints中可调整与 Find 相关的全局行为配置项类型默认值说明rest((boolean))true是否启用GET /:model这类 REST 蓝图路由shortcuts((boolean))true是否启用GET /:model/find这类 shortcut 路由仅建议开发期使用prefix((string))所有蓝图路由的挂载前缀如/api/v2pluralize((boolean))false是否使用复数模型名/users对应User模型autoWatch((boolean))true是否在 find/findOne 蓝图动作中订阅新建记录通知parseBlueprintOptions((function))默认实现覆盖蓝图动作默认解析行为的钩子函数Sails 1.0 起sails.config.blueprints.defaultLimit与sails.config.blueprints.populate已不再受支持见 blueprints 钩子 configure默认 limit 固定为 30、默认填充全部关联。如需自定义请使用parseBlueprintOptions。用 parseBlueprintOptions 覆盖默认行为Find 蓝图本质上就是解析请求 → 调用 Waterline 模型方法。其中Model.find()的查询选项完全由parseBlueprintOptions(req)决定默认实现可通过sails.hooks.blueprints.parseBlueprintOptions()访问也允许你在全局或单路由级别覆盖参考配置文档。例如限制 Find 请求的limit上限为 100// config/blueprints.js module.exports.blueprints { parseBlueprintOptions: function(req) { // 先取默认查询选项 var queryOptions req._sails.hooks.blueprints.parseBlueprintOptions(req); // 若是 find / populate 蓝图动作且请求试图设置过大的 limit则强制截断为 100 if (req.options.blueprintAction find || req.options.blueprintAction populate) { if (queryOptions.criteria.limit 100) { queryOptions.criteria.limit 100; } } return queryOptions; } };按控制器禁用蓝图使用传统 controller而非独立 action 文件时可以在控制器内定义_config按控制器关闭对应蓝图路由该做法仅出于兼容性保留推荐直接使用自定义路由// 在 /api/controllers/PetController.js module.exports { _config: { actions: false, shortcuts: false, rest: false } }与 FindOne 蓝图的分工Find 蓝图对应列表查询GET /:model而单条查询由 FindOne 蓝图GET /:model/:id负责。两者共享同一套参数解析入口但 findOne.js 会把 criteria 严格裁剪为where/select/omit且where仅保留主键字段未找到记录时返回 404而 Find 始终返回数组可能为空。快速上手复现本文示例以下步骤可以完整复现文中所有示例假设 REST 蓝图开启、项目含Purchase模型$ sails new foo $ cd foo $ sails generate model purchase $ sails lift # 会看到数据库自动迁移设置提示。 # 选择 1 (alter) 后按 ENTER。启动后访问http://localhost:1337/purchase?sortcreatedAt DESClimit30即可得到与期望响应一致的结果列表。若要验证 socket 订阅可在项目中引入 sails.io.js 并用io.socket.get()发起请求随后在其他客户端更新或删除返回的记录观察 socket 客户端是否收到变更通知。【免费下载链接】sailsRealtime MVC Framework for Node.js项目地址: https://gitcode.com/gh_mirrors/sa/sails创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考