【问题标题】:Matching phone numbers in address book with Firestore将地址簿中的电话号码与 Firestore 匹配
【发布时间】:2020-09-03 17:56:59
【问题描述】:

我正在尝试快速将来自 Firestore 的电话号码列表与用户的通讯录进行比较和匹配。这行得通,但速度很慢,尤其是来自 firestore 的更多数字,我认为逻辑完全错误,需要修复。

// Array of Strings containing all the phone numbers that are registered on the app are passed through the function.

  func searchForContactUsingPhoneNumber(phoneNumberArray: [String]) -> [CNContact] {
    var result: [CNContact] = []
    let phoneNumberKit = PhoneNumberKit()

    // go through all contacts in the address book for contact in self.contacts {

        if !contact.phoneNumbers.isEmpty {

         let parsedNumberArray = try? phoneNumberKit.parse(phoneNumberArray, withRegion: "GB",  ignoreType: true)

         for singleNumber in parsedNumberArray! {

            let databaseNumber = singleNumber.nationalNumber

            //go through every number of each contach
            for phoneNumber in contact.phoneNumbers {
                let fulMobNumVar  = phoneNumber.value
                let number = fulMobNumVar.value(forKey: "digits") as? String

                let parsedNumber = try? phoneNumberKit.parse(number!, withRegion: "GB", ignoreType: true)
                let contactNumber = parsedNumber?.nationalNumber

                //compare phoneNumber of contact with given users phone number
               if contactNumber == databaseNumber {
                    result.append(contact)
                }

            }
        }
    }
    }

    return result
}

编辑

有 3 个电话号码列表:

firestore 中的一个列表,其中存储已在应用程序上注册的用户的每个电话号码。当任何新用户在应用程序上注册时,他们的电话号码就会添加到该列表中。将此列表与用户自己的电话通讯簿进行比较。

第二个列表是用户通讯录(联系人)。如果 firebase 中的电话号码与地址簿匹配,则该号码将添加到特定用户文档中 firebase 内的第三个列表中。

第三个列表是我正在尝试生成的特定于应用程序的列表,其中包含用户通讯录和所有电话号码的大列表之间的匹配项。

【问题讨论】:

  • 代码的用途是什么?换句话说,声明是在地址簿和firebase之间比较和匹配电话号码 - 为什么?是否需要获取firebase中的号码并将其添加到联系人或获取不在firebase中的联系人号码并添加它们?或者是其他东西?我在问,因为答案取决于用例。在高层次上,您可以获取联系人中的所有数字并将它们放入一个集合中,对 Firebase 中的所有数字执行相同的操作,并使用这些集合,您可以通过一行代码找到它们的交集或对称差.
  • 感谢您的回复!目的是当用户通讯录中的号码与 firebase 中的号码列表匹配时,匹配的电话号码将添加到应用程序中的用户联系人列表中。匹配的号码将添加到 Firestore 中的用户联系人列表中。尝试重新创建与 WhatsApp 类似的功能,用户通讯录中拥有 WhatsApp 的每个号码都将出现在用户 WhatsApp 联系人列表中。
  • 所以有三个电话号码列表; 1)用户联系人 2)存储在 Firestore 中的号码列表 3)存储在应用程序联系人中?存储在 Firestore 中的数据与存储在应用程序联系人中的数据有什么区别 - 您不是将应用程序数据存储在 Firestore 中吗? 2)中的数字来自哪里?最后一个问题; 1) 和 2) 中一般有多少电话号码?
  • 抱歉没有说清楚。是的,有 3 个电话号码列表。 Firestore 上有 1 个列表 (LIST A),其中存储了在应用程序上注册的用户的每个电话号码。当任何新用户在应用程序上注册时,他们的电话号码就会添加到该列表中。此列表与用户自己的电话通讯簿(列表 2)进行比较。如果 firebase 中的电话号码与地址簿匹配,则该号码将添加到特定用户文档 (LIST3) 内 firebase 内的第三个列表中。列表 1 将包含更多的数字。
  • 完美。我更新了你的问题。有很多方法可以做到这一点,所以我会尽快回答。

标签: ios swift firebase google-cloud-firestore


【解决方案1】:

这里的目标是在应用程序中创建一个电话号码列表,其中所有用户电话号码的主列表与存储在用户通讯录(联系人)中的电话号码之间存在匹配。

用一些示例数据更好地说明:

phone_master
   docId_0
      phone: "222-222-2222"
      uid: "uid_2"
   docId_1
      phone: "333-333-3333"
      uid: "uid_3"

在上面,我们收集了所有使用该应用的用户电话号码。每个文档都包含电话号码,然后是拥有它的用户的 uid。

users
   uid_1
      name: "Hank"
      phone_numbers: (a collection)
         docId_0:
            phone: "222-222-2222"
            uid: "uid_2"

在 users 集合中,用户 Hank 已经有一个电话号码存储在他们的应用程序 222-222-2222 中,这是 uid_2 的号码。

以下内容将扫描存储在 firebase 主列表中的所有号码,并将任何匹配项添加到应用内 Hank 的电话列表中。当其他用户添加到应用程序中时,它还会监听任何未来的比赛。

这里的问题是,一旦将数字添加到应用程序中,我们就不想再次添加它。

前两行是样本数据数组:

addressBookNumbers - the numbers that are stored in the users address book, not the app
appNumbers - these are the numbers that have already been added

我假设 OP 可以从 Firestore 中读取地址簿号码和现有应用程序号码并将它们存储在一个数组中。

还有代码:

func generateContactList() {
    let addressBookNumbers = ["111-111-1111", "222-222-2222", "333-333-3333", "444-444-4444"]
    let appNumbers = ["222-222-2222"]
    let thisUser = "uid_1"

    let allPhonesCollection = self.db.collection("phone_master")
    allPhonesCollection.addSnapshotListener { querySnapshot, error in
        guard let snapshot = querySnapshot else {
            print("Error fetching snapshots: \(error!)")
            return
        }

        snapshot.documentChanges.forEach { diff in
            if (diff.type == .added) {
                let phone = diff.document.get("phone") as? String ?? "No Phone"

                //see if this number has already been added to the app
                if appNumbers.contains(phone) {
                    return
                }

                //ignore the number if it's not in the addresssbook
                if !addressBookNumbers.contains(phone) {
                    return
                }

                let contactsUid = diff.document.get("uid") as? String ?? "No uid"

                //if we get here, we know the number from the master list is in
                //  this users address book, so add it to the app
                let usersCollection = self.db.collection("users")
                let thisUserDoc = usersCollection.document(thisUser)
                let phoneCollection = thisUserDoc.collection("phone_numbers")
                let data = ["number": phone,
                            "uid": contactsUid]
                phoneCollection.document().setData(data)
            }
            if (diff.type == .modified) {
                let docId = diff.document.documentID
                print(docId)
            }
            if (diff.type == .removed) {
                let docId = diff.document.documentID
                print(docId)
            }
        }
    }
}

代码运行后,汉克斯文档是这样的

users
   uid_1
      name: "Hank"
      phone_numbers: (a collection)
         docId_0:
            phone: "222-222-2222"
            uid: "uid_2"
         docId_1:
            phone: "333-333-3333"
            uid: "uid_3"

【讨论】:

  • 这很完美!非常感谢。但是,这将如何扩展?例如,如果有 100 个新用户加入,它会不会显着减慢,必须比较和匹配添加到 allPhonesCollection 的每个新号码。
  • @shwankadir 好问题。 Firebase 速度非常快,因此迭代这些节点的速度很快,除了匹配的节点之外,您实际上并没有在代码中进行任何处理,因此这将很好地扩展。但是,如果您要处理大量数据,您也可以限制搜索内容;例如使用日期。您可以存储用户登录的最后日期,并为电话号码节点加上时间戳,然后不要使用.addSnapshotListener 监听所有文档,而是对该日期之后的文档进行查询并为这些文档添加监听器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多