Google cloud firestore Firestore唯一索引还是唯一约束?
在Firestore中是否可以定义具有唯一约束的索引?如果没有,如何在文档字段上强制唯一性(不使用文档ID)?是的,这可以使用两个集合、Firestore规则和批处理写入的组合 简单的想法是,使用批处理写入,将文档写入“数据”集合,同时写入单独的“索引”集合,在该集合中为要唯一的字段值编制索引 然后,使用Firestore规则,您可以确保“数据”集合只能在文档字段的值也存在于索引集合中时写入文档,反之亦然,如果索引中的值与数据集合中的值匹配,则只能将索引集合写入 示例 假设我们有一个Google cloud firestore Firestore唯一索引还是唯一约束?,google-cloud-firestore,Google Cloud Firestore,在Firestore中是否可以定义具有唯一约束的索引?如果没有,如何在文档字段上强制唯一性(不使用文档ID)?是的,这可以使用两个集合、Firestore规则和批处理写入的组合 简单的想法是,使用批处理写入,将文档写入“数据”集合,同时写入单独的“索引”集合,在该集合中为要唯一的字段值编制索引 然后,使用Firestore规则,您可以确保“数据”集合只能在文档字段的值也存在于索引集合中时写入文档,反之亦然,如果索引中的值与数据集合中的值匹配,则只能将索引集合写入 示例 假设我们有一个用户集合,
用户
集合,我们希望确保用户名
字段是唯一的
我们的用户
集合只包含用户名
/User/{id}
{
username: String
}
我们的索引
集合将在路径中包含用户名和一个值
属性,该属性包含被索引用户的id
/Index/User/username/{username}
{
value: User.id
}
为了创建我们的用户
,我们使用批写入同时创建用户
文档和索引
文档
const firebaseApp=…构建您的firebase应用程序
const createUser=async(用户名)=>{
const database=firebaseApp.firestore()
const batch=database.batch()
const Collection=database.Collection('用户')
const ref=Collection.doc()
批次设置(参考{
用户名
})
const Index=database.collection('Index')
const indexRef=Index.doc(`User/username/${username}`)
batch.set(索引外部参照{
值:ref.id
})
等待批处理。提交()
}
要更新我们的用户
的用户名,我们使用批写入来更新用户
文档,删除以前的索引
文档,并同时创建一个新的索引
文档
const firebaseApp=…构建您的firebase应用程序
const updateUser=async(id,username)=>{
const database=firebaseApp.firestore()
const batch=database.batch()
const Collection=database.Collection('用户')
const ref=Collection.doc(id)
const refDoc=wait ref.get()
const prevData=refDoc.data()
批次更新(参考{
用户名
})
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(索引外部参照{
值:ref.id
})
等待批处理。提交()
}
要删除用户
,我们使用批写入同时删除用户
文档和索引
文档
const firebaseApp=…构建您的firebase应用程序
const deleteUser=async(id)=>{
const database=firebaseApp.firestore()
const batch=database.batch()
const Collection=database.Collection('用户')
const ref=Collection.doc(id)
const refDoc=wait ref.get()
const prevData=refDoc.data()
批处理删除(参考)
const Index=database.collection('Index')
const indexRef=Index.doc(`User/username/${prevData.username}`)
批处理.删除(索引外部参照)
等待批处理。提交()
}
然后,我们设置Firestore规则,使其仅允许在未为不同的用户
编制用户名索引的情况下创建用户
。用户
的用户名只有在用户名的索引
不存在时才能更新,而用户
只有在索引
也被删除时才能删除。如果已经存在具有相同用户名的用户
,则创建和更新将失败,并出现“缺少或权限不足”错误
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;
}
}
}
[这不是一个完美的解决方案,但有效]
我用钥匙做了这个独特的钥匙。。。
我希望我的表具有唯一的日期值。所以我把它作为我文件的关键。
我能得到所有的文件吗
db.collection('sensors').doc(sensorId).collection("data").doc(date).set(dataObj).then(() => {
response.send(dataObj);
});
基于本节中的文档
向集合添加文档对象时,只需添加自定义标识符,如下所示:
const data = {
name: 'Los Angeles',
state: 'CA',
country: 'USA'
};
// Add a new document in collection "cities" with ID 'LA'
const res = await db.collection('cities').doc('LA').set(data);
使用此项作为参考当您在收藏中使用set作为方法时,您可以为此类文档指定一个id,当您需要自动生成id时,您只需在收藏中使用add方法即可否,目前不可能这样做。在这里查看我的答案。这是一个非常聪明的解决方案,但是,要处理一个非常基本的缺失功能肯定需要大量的工作。出于某种原因,在一个空的firestore中,我在每次创建尝试时都会遇到“缺失或权限不足”错误。如果临时删除规则集,则可以创建索引和用户记录。如果我再次添加规则集,则每个创建请求都会失败。有什么想法/建议吗?清楚的解决方案,但您可以为文档设置标识符,而不是使用批处理。请看下面我的解决方案。我回答的问题是:“不使用文档ID”,因为我不能这样做。我回答的问题是:“不使用文档ID”,因为我不能这样做。