开始使用
R2D1 的设置从两个后端选择开始,之后进入一条通用 API 流程。选择完整文档的存储位置和索引字段的存储位置,然后用这两个 store 配置集合 facade。
1. 选择文档存储
DocumentStore 是完整序列化文档、按标识读取和逻辑存在性的权威来源。请选择一个:
- R2 DocumentStore 通过 AWS SDK 异步客户端将文档存储在 Cloudflare R2。
- Filesystem DocumentStore 使用原子替换保存规范的本地文档。
2. 选择索引存储
IndexStore 是文档标识和显式索引字段的可重建投影。请选择一个:
- D1 IndexStore 通过 Java 异步 HttpClient 使用 Cloudflare D1 REST API。
- JDBC IndexStore 通过应用拥有的 DataSource 支持 H2、HSQLDB 和本地 SQLite。
这些选择形成 R2 + D1、R2 + JDBC、Filesystem + D1 和 Filesystem + JDBC 四种组合,但不会产生四套不同的集合 API。
3. 添加所需模块
核心 artifact 提供通用 API 以及 Cloudflare R2/D1 适配器:
dependencies {
implementation("dev.nexcraft:r2d1:<version>")
}只添加应用实际使用的集成模块:
dependencies {
implementation("dev.nexcraft:r2d1-filesystem:<version>")
implementation("dev.nexcraft:r2d1-jdbc:<version>")
implementation("dev.nexcraft:r2d1-micronaut:<version>")
}JDBC 驱动由应用提供,r2d1-jdbc 不会将其打包。完整的模块表和所有权规则请参阅 Configuration.
4. 定义文档
为一个非空 String 成员添加 @Id 作为标识,并为需要写入索引的字段添加 @Index。只有显式索引的字段才能参与过滤和排序。
import dev.nexcraft.r2d1.annotation.Document;
import dev.nexcraft.r2d1.annotation.Id;
import dev.nexcraft.r2d1.annotation.Index;
@Document("users")
public record User(
@Id String id,
@Index String country,
@Index long score,
String name) {}R2D1 不选择 JSON library。请提供 DocumentCodec,将 domain object 序列化为 StoredDocument,并在集合生成结果时再次反序列化。
5. 配置通用集合 API
下面的示例将适配器创建留给应用,以便清楚展示两个存储角色。documentStore、indexStore 和 documentCodec 都由应用拥有。
import dev.nexcraft.r2d1.DocumentCodec;
import dev.nexcraft.r2d1.PersistenceCollectionFactory;
import dev.nexcraft.r2d1.R2D1;
import dev.nexcraft.r2d1.R2D1Collection;
import dev.nexcraft.r2d1.spi.DocumentStore;
import dev.nexcraft.r2d1.spi.IndexStore;
DocumentStore documentStore = applicationDocumentStore;
IndexStore indexStore = applicationIndexStore;
DocumentCodec documentCodec = applicationDocumentCodec;
R2D1 database =
R2D1.builder()
.collectionFactory(
new PersistenceCollectionFactory(
documentStore, indexStore, documentCodec, indexStore::initialize))
.build();
R2D1Collection<User> users = database.collection(User.class);打开集合时,R2D1 会先初始化或验证集合 metadata,然后返回集合。factory 不会接管 store、codec 或调用方拥有的执行资源。
6. put、get 和 delete
User user = new User("user-123", "NZ", 42, "Ada");
users.put(user);
Optional<User> stored = users.get("user-123");
users.delete("user-123");
Optional<User> absent = users.get("user-123");put 使用 @Id 值创建或替换文档。get 读取权威文档存储,删除不存在的标识不会产生效果。
7. 运行索引查询
import dev.nexcraft.r2d1.Page;
import dev.nexcraft.r2d1.SortDirection;
Page<User> first =
users.query()
.where("country")
.eq("NZ")
.sortBy("score", SortDirection.DESC)
.limit(20)
.fetch();
if (first.nextCursor() != null) {
Page<User> second =
users.query()
.where("country")
.eq("NZ")
.sortBy("score", SortDirection.DESC)
.limit(20)
.after(first.nextCursor())
.fetch();
}cursor 是不透明值。请求下一页时保持相同的 filter 和 sort。支持的比较运算符和排序规则请参阅 Querying;在生产环境使用两个 store 前,请阅读 Consistency and Recovery.
