firebase - 如何在 Firestore 事务中实现 getOrCreate?
问题描述
我正在尝试实施报价书签服务。
- 给定一个报价集合,它有四个信息——报价、userId、authorId 和 sourceId。
- 给定一个作者集合,它有两个信息 - 名称、用户 ID
- 给定一个源集合,它具有三个信息 - 名称(星球大战)、类型(书籍、电影)、用户 ID
当用户尝试保存报价时,我想要一个交易来检查作者是否存在(通过名称查询。如果是,则返回 authorId。如果不,则创建作者)。源+类型也是如此。作者和来源都将返回各自的 ID。在保存报价时,报价对象将使用authorId和sourceId创建。
这种情况可能吗?我检查了 Firestore.firestore().transaction 中只有 getDocument 函数,我无法使用 whereField() 进行查询。
我在某处读过,我们可以通过规则强制执行创建,并在 try/catch 中抛出错误或某种错误,其中 catch 块将执行 getDocument?
如果我无法在事务中进行查询并且只能依赖 getDocument,这是否意味着作者/源集合的 ID 必须是一个复合键,例如“userId + hash(作者/源名称)” ?
执行此类操作有什么建议?还是 Firestore 无法处理这样的用例?
总之,我正在尝试这样做(在伪代码中)......
Firestore.transaction {
// Get or create author
let author = Author.getOrCreate("Yoda", userId)
// Get or create source
let source = Source.getOrCreate("Star Wars", "film", userId)
// Save quote
let quote = Quote.create({
quote: "Do or do not. There is no try",
authorId: author.id,
sourceId: source.id,
userId: userId
})
}
解决方案
在事务中,所有读取都应该先进行。您可以使用transaction.getAll()
获取作者和来源,如果它们不存在则创建它们:
const authorsRef = db.collection('authors')
const sourcesRef = db.collection('sources')
const quotesRef = db.collection('quotes')
db.runTransaction(transaction => transaction
.getAll(
authorsRef.where('name', '==', 'Yoda').get(),
sourcesRef.where('name', '==', 'Star Wars').where('type', '==', 'film').get()
)
.then(([ authorDoc, sourceDoc ]) => {
let author = authorDoc
let source = sourceDoc
if (!author.exists) {
author = authorsRef.doc()
transaction.set(author, { /* add author fields here */ })
}
if (!source.exists) {
source = sourcesRef.doc()
transaction.set(source, { /* add source fields here */ })
}
transaction.set(quotesRef.doc(), {
// add other quote fields here
authorId: author.id,
sourceId: source.id
})
})
)
推荐阅读
- php - 通过 composer ( laravel/scout ) 在 laravel 上安装包时出错
- javascript - 表保存 cookie 中的列位置
- node.js - 如何共享 node_module 而不是每次都安装它
- spring - 删除了 spring initializr 2.3.x
- azure - 使用 Azure Devops yaml 管道部署到本地服务器
- graph - Cypher:为特定类型的每个节点获取 n 个相邻节点
- javascript - 如何将块插件添加到grapesjs?
- qt - 如果我在窗口之间来回切换,QMessageBox 会多次打开的问题
- c - 是什么导致我的指针不更新其指向的地址并显示正确的值?
- json - 如何转换 JSON 对象打字稿符合?