gpt4 book ai didi

google-cloud-firestore - Firestore 唯一索引或唯一约束?

转载 作者:行者123 更新时间:2023-12-04 11:06:49 30 4
gpt4 key购买 nike

是否可以在 Firestore 中定义具有唯一约束的索引?如果没有,如何在文档字段上强制执行唯一性(不使用文档 ID)?

最佳答案

是的,这可以通过结合使用两个集合、Firestore 规则和批量写入来实现。

https://cloud.google.com/firestore/docs/manage-data/transactions#batched-writes

简单的想法是,使用批量写入,您将文档写入“数据”集合,同时写入单独的“索引”集合,在其中索引要唯一的字段的值。

使用 Firestore 规则,您可以确保“数据”集合只能在文档字段的值也存在于索引集合中的情况下才能写入文档,反之亦然,如果值,则只能写入索引集合索引中的内容与数据集合中的内容相匹配。

示例

假设我们有一个 User集合,我们要确保username字段是唯一的。

我们的 User集合将只包含 username

/User/{id}
{
username: String
}

我们的 Index集合将包含路径中的用户名和 value包含被索引用户的 id 的属性。
/Index/User/username/{username}
{
value: User.id
}

创建我们的 User我们使用批量写入来创建 User文档和 Index同时文档。

const firebaseApp = ...construct your firebase app

const createUser = async (username) => {
const database = firebaseApp.firestore()
const batch = database.batch()

const Collection = database.collection('User')
const ref = Collection.doc()
batch.set(ref, {
username
})

const Index = database.collection('Index')
const indexRef = Index.doc(`User/username/${username}`)
batch.set(indexRef, {
value: ref.id
})

await batch.commit()
}

更新我们的 User的用户名我们使用批量写入来更新 User文档,删除之前的 Index文档并创建一个新的 Index同时记录所有文件。

const firebaseApp = ...construct your firebase app

const updateUser = async (id, username) => {
const database = firebaseApp.firestore()
const batch = database.batch()

const Collection = database.collection('User')
const ref = Collection.doc(id)
const refDoc = await ref.get()
const prevData = refDoc.data()
batch.update(ref, {
username
})

const Index = database.collection('Index')
const prevIndexRef = Index.doc(`User/username/${prevData.username}`)
const indexRef = Index.doc(`User/username/${username}`)
batch.delete(prevIndexRef)
batch.set(indexRef, {
value: ref.id
})

await batch.commit()
}

删除 User我们使用批量写入来删除 User文档和 Index同时文档。

const firebaseApp = ...construct your firebase app

const deleteUser = async (id) => {
const database = firebaseApp.firestore()
const batch = database.batch()

const Collection = database.collection('User')
const ref = Collection.doc(id)
const refDoc = await ref.get()
const prevData = refDoc.data()
batch.delete(ref)


const Index = database.collection('Index')
const indexRef = Index.doc(`User/username/${prevData.username}`)
batch.delete(indexRef)

await batch.commit()
}

然后我们设置我们的 Firestore 规则,以便它们只允许 User如果用户名尚未为不同的 User 编入索引,则创建.一个 User的用户名只能在 Index 时更新用户名和 User 不存在只有在 Index 时才能删除也被删除。如果出现 User,创建和更新将失败并显示“权限缺失或不足”错误。同 username已经存在。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {


// Index collection helper methods

function getIndexAfter(path) {
return getAfter(/databases/$(database)/documents/Index/$(path))
}

function getIndexBefore(path) {
return get(/databases/$(database)/documents/Index/$(path))
}

function indexExistsAfter(path) {
return existsAfter(/databases/$(database)/documents/Index/$(path))
}

function indexExistsBefore(path) {
return exists(/databases/$(database)/documents/Index/$(path))
}


// User collection helper methods

function getUserAfter(id) {
return getAfter(/databases/$(database)/documents/User/$(id))
}

function getUserBefore(id) {
return get(/databases/$(database)/documents/User/$(id))
}

function userExistsAfter(id) {
return existsAfter(/databases/$(database)/documents/User/$(id))
}


match /User/{id} {
allow read: true;

allow create: if
getIndexAfter(/User/username/$(getUserAfter(id).data.username)).data.value == id;

allow update: if
getIndexAfter(/User/username/$(getUserAfter(id).data.username)).data.value == id &&
!indexExistsBefore(/User/username/$(getUserAfter(id).data.username));

allow delete: if
!indexExistsAfter(/User/username/$(getUserBefore(id).data.username));
}

match /Index/User/username/{username} {
allow read: if true;

allow create: if
getUserAfter(getIndexAfter(/User/username/$(username)).data.value).data.username == username;

allow delete: if
!userExistsAfter(getIndexBefore(/User/username/$(username)).data.value) ||
getUserAfter(getIndexBefore(/User/username/$(username)).data.value).data.username != username;
}
}
}

关于google-cloud-firestore - Firestore 唯一索引或唯一约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47543251/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com