如何通过API修改$byCategory投影?如何自动设置EventStore中该投影为last?
修改EventStore的$byCategory系统投影及自动设置为last的方法
一、通过API修改$byCategory投影
$byCategory是EventStore的内置系统投影,默认用来按分类(优先取事件元数据的$category,无则用事件类型前缀)把事件链接到对应分类流。要修改它,得通过EventStore的投影API操作,步骤如下:
- 确认权限:确保你有EventStore的管理员权限(默认用户名
admin,密码changeit),系统投影的修改需要高权限才能执行。 - 获取当前投影定义:发送GET请求拿到投影的查询逻辑:
响应的JSON里,curl -X GET http://localhost:2113/projection/$by_category -u admin:changeitquery字段就是投影的JavaScript代码,这是我们要修改的核心部分。 - 调整为last模式的逻辑:如果希望每个分类流只保留最新的事件,需要在
linkTo方法里加overwrite: true参数(覆盖该分类流的旧事件),示例修改后的query:fromAll() .when({ $any: function(state, event) { // 提取分类:先看元数据的$category,没有就用事件类型的前缀(比如UserCreated -> User) var category = event.metadata["$category"] || event.type.split('-')[0]; // 链接事件到分类流,overwrite: true会替换该流的最后一个事件 linkTo(category, event, { overwrite: true }); } }) - 提交修改后的投影:发送PUT请求把新的query提交给API:
执行后投影会重新处理事件,之后每个分类流就只会保留最新的那条事件了。curl -X PUT http://localhost:2113/projection/$by_category/query \ -u admin:changeit \ -H "Content-Type: application/json" \ -d '{ "query": "fromAll().when({$any: function(state, event) { var category = event.metadata[\"$category\"] || event.type.split(\"-\")[0]; linkTo(category, event, { overwrite: true }); }})" }'
二、自动设置为last的实现方式
EventStore没有直接的启动参数能预设系统投影的逻辑,但可以通过两种方式自动完成配置:
1. 启动后自动执行API脚本
可以写一个启动脚本,等EventStore完全启动后,自动调用上述API修改投影。比如在shell脚本里:
# 等待EventStore启动完成(时间根据实际情况调整) sleep 10 # 更新$byCategory投影为last模式 curl -X PUT http://localhost:2113/projection/$by_category/query \ -u admin:changeit \ -H "Content-Type: application/json" \ -d '{ "query": "fromAll().when({$any: function(state, event) { var category = event.metadata[\"$category\"] || event.type.split(\"-\")[0]; linkTo(category, event, { overwrite: true }); }})" }'
把这个脚本和EventStore的启动命令绑定(比如docker-compose的command里,或者systemd服务的ExecStartPost),就能实现启动后自动配置。
2. 创建自定义持久化投影(更推荐)
因为系统投影在EventStore升级时可能被重置,更稳妥的做法是创建一个自定义投影替代$byCategory,设置为持久化并自动启动:
- 发送POST请求创建新投影:
这个自定义投影会永久保留你的配置,不会被系统升级影响,而且启动后会自动运行。curl -X POST http://localhost:2113/projections/transient \ -u admin:changeit \ -H "Content-Type: application/json" \ -d '{ "name": "$by_category_last", "query": "fromAll().when({$any: function(state, event) { var category = event.metadata[\"$category\"] || event.type.split(\"-\")[0]; linkTo(category, event, { overwrite: true }); }})", "enabled": true, "emitEnabled": true, "persistState": true }'
注意事项
- 修改系统投影前,建议先备份数据,避免意外丢失事件链接。
- 如果你的EventStore开了安全认证,要确保API请求携带正确的认证信息。
overwrite: true是针对链接事件到流的操作,会替换目标流的最后一个事件;如果需要的是其他"last"逻辑(比如只追踪每个分类的最后事件状态),可以调整投影里的state处理逻辑。
内容的提问来源于stack exchange,提问作者Andriy Drozdyuk
相关产品推荐
相关产品推荐

