Firebase Firestore:对集合中文档的循环访问

Firebase Firestore:对集合中文档的循环访问,firebase,google-cloud-firestore,Firebase,Google Cloud Firestore,我想做一些非常简单的事情,但不确定用Firestore做这件事的最佳方式 我有一个广告收藏 每次访问ad时,我都要更新accessed属性时间戳,以便只显示在最长时间内未显示的广告 我的安全规则只允许携带有效负载为admin:true的令牌的用户创建/修改ads 因此,在应用程序中,我无法在每次访问广告时更新时间戳,因为用户不是管理员 我考虑过为此创建一个函数,但意识到没有onGet函数允许我这么做() 我认为无论如何都不允许任何用户修改单个属性 使用Firestore进行此操作的合适方法是什么

我想做一些非常简单的事情,但不确定用Firestore做这件事的最佳方式

我有一个
广告
收藏

每次访问
ad
时,我都要更新
accessed
属性时间戳,以便只显示在最长时间内未显示的广告

我的安全规则只允许携带有效负载为
admin:true
的令牌的用户创建/修改
ads

因此,在应用程序中,我无法在每次访问广告时更新时间戳,因为用户不是管理员

我考虑过为此创建一个函数,但意识到没有
onGet
函数允许我这么做()

我认为无论如何都不允许任何用户修改单个属性


使用Firestore进行此操作的合适方法是什么?

您可以通过创建一个非常全面的规则验证来解决此问题,在该验证中,您可以检查除访问的
以外的所有字段是否保持不变。您可以使用实现管理员角色概念,如中所述

检查除访问的
以外的所有字段是否保持不变,需要您逐个列出并检查所有字段

service cloud.firestore {
  match /databases/{database}/documents {

    match /ads/{id} {
        allow read: if true; 
      allow write: if request.auth.token.admin == true 
            || (request.resource.data.someField == resource.data.someField
        && request.resource.data.anotherField == resource.data.anotherField);
    }
  }
}
另一种方法是创建一个类似的。您只需在每次阅读广告时从客户机调用它,就可以安全地在该函数中更新帖子上的
访问的
字段

export const touchAd=functions.https.onCall((数据,上下文)=>{
const adId=data.id;
返回admin.firestore().collection('ads').doc(adId).更新({
已访问:firebase.firestore.FieldValue.serverTimestamp(),
}));
});

您可以通过创建一个非常全面的规则验证来解决这个问题,在该验证中,您可以检查除访问的
以外的所有字段是否保持不变。您可以使用实现管理员角色概念,如中所述

检查除访问的
以外的所有字段是否保持不变,需要您逐个列出并检查所有字段

service cloud.firestore {
  match /databases/{database}/documents {

    match /ads/{id} {
        allow read: if true; 
      allow write: if request.auth.token.admin == true 
            || (request.resource.data.someField == resource.data.someField
        && request.resource.data.anotherField == resource.data.anotherField);
    }
  }
}
另一种方法是创建一个类似的。您只需在每次阅读广告时从客户机调用它,就可以安全地在该函数中更新帖子上的
访问的
字段

export const touchAd=functions.https.onCall((数据,上下文)=>{
const adId=data.id;
返回admin.firestore().collection('ads').doc(adId).更新({
已访问:firebase.firestore.FieldValue.serverTimestamp(),
}));
});