文件子集的监听器

时间:2019-08-17 12:41:06

标签: swift google-cloud-firestore listener one-to-many

使用Firestore,侦听器是关注集合中文档更改的好方法。

let listener = db.collection("cities").whereField("state", isEqualTo: "CA")
    .addSnapshotListener { querySnapshot, error in
        guard let snapshot = querySnapshot else {
            print("Error fetching snapshots: \(error!)")
            return
        }
        snapshot.documentChanges.forEach { diff in
            if (diff.type == .added) {
                print("New city: \(diff.document.data())")
            }
            if (diff.type == .modified) {
                print("Modified city: \(diff.document.data())")
            }
            if (diff.type == .removed) {
                print("Removed city: \(diff.document.data())")
            }
        }
    }

在本文档中的代码示例中,使用查询在等于“ CA”的固定字段“ state”上放置了侦听器。该州与城市静态相关联,只能有一个答案(即一对一)。

  

城市-> CA

一对多(选项1): 如果我们正在开发旅游应用程序,并且要听的“城市”文档是根据对那个城市感兴趣的单个用户(一对多)定义的,则可以在每个“城市”文档中添加一个字段,以使查询成为可能使用相同的方法。

  

城市A->用户1,用户2,用户3

     

CityB-> User1,User3,User4

在包含User1的城市上运行查询,将使用User1作为字段捕获所有城市。但是,这违反了将文档保持较小且固定长度的设计规则。随着每个新用户的添加,城市文档将继续增长。另外,还会向所有其他用户发送新用户对同一个城市感兴趣的触发器,这可能对他们来说并不是很有用。

选项2: 解决一对多问题的另一种方法是添加另一个名为“ UserCities”的集合,其中包含显示每个用户感兴趣的城市的文档。

  

用户1-> CityA,CityB

     

User2-> CityA

     

User3-> CityA,CityB

对于要由“城市”集合中的城市文档的更改触发的每个用户,都需要在“ UserCities”集合中对该城市的每个实例进行额外的写操作。但这会导致很多额外的写操作,但是这些写操作很昂贵,而且从编码角度来看似乎也不是很优雅。

选项3: 第三种方法可能是在“城市”下创建一个名为“用户”的子集合。

  

城市A

     

|-> User1,User2,User3

     

城市B

     

|-> User1,User2,User4

Firestore团队不久前添加了在子集合内的字段上运行查询的功能,这确实很酷。但是,将其用于侦听器也会遇到问题,因为侦听器不会拾取子集合(或父集合)中的更改,并且当任一CityA时,都不会触发User1的“用户”子集合上的侦听器或CityB在“城市”集合中获得更新。解决此问题遇到了多次写入集合和子集合的问题。

选项3b: 或者,我们可以对“用户”子集合上的侦听器执行某些操作,以根据该侦听器的结果在此首先获取更改,然后对“城市”集合中的第二个侦听器进行更改。为此,我们仍然需要以某种方式基于第一个侦听器在“城市”上定义该侦听器。

编辑:经过进一步的挖掘,此第三个选项被正确称为收集组查询。如果在侦听器中使用此代码,则其代码如下所示:

let listener = db.collectionGroup("users").whereField("user", isEqualTo: "User1")
    .addSnapshotListener { querySnapshot, error in
        guard let snapshot = querySnapshot else {
            print("Error fetching snapshots: \(error!)")
            return
        }
        snapshot.documentChanges.forEach { diff in
            if (diff.type == .added) {
                print("New user: \(diff.document.data())")
            }
            if (diff.type == .modified) {
                print("Modified user: \(diff.document.data())")
            }
            if (diff.type == .removed) {
                print("Removed user: \(diff.document.data())")
            }
        }
    }

对于集合组查询,我了解到需要在控制台中设置索引,这将解决另一个问题。

因此,我们基本上正在研究三种方法,每种方法都有明显的缺点,因为它们涉及额外的写操作或违反了文档的设计规则。也许很多写入只是我们在NoSQL世界中必须接受的一个缺点,但是Firestore试图使用集合克服这些问题的需要。我希望其他许多人也面临这个选择。我想知道您是否找到了比这三个更好的解决方案,并且可以提出建议。

0 个答案:

没有答案