计算Firebase中共同朋友的数量

时间:2017-09-23 19:50:18

标签: swift firebase swift3 firebase-realtime-database

我正在尝试用任何给定的用户ID拉出我拥有的共同朋友的数量。我首先从Firebase中拉出了所有朋友,然后我拉出了userID的朋友。我只是不确定如何计算那里的共同朋友的数量。如果我以错误的方式去做,请告诉我。

func fetchMutualFriends(myID: String, userID: String) {

    let myID = Auth.auth().currentUser!.uid

    let postRef = self.databaseRef.child("friends").child(myID)

    postRef.observe(.value, with: { (snapshot) in
        for childSnapshot in snapshot.children {
              print(childSnapshot)

        }
    })
    let postRef1 = self.databaseRef.child("friends").child(friendID)

    postRef1.observe(.value, with: { (snapshot) in
        for childSnapshot in snapshot.children {
            print(childSnapshot)

        }
    })
}

Firebase结构

root/
|___ friends/
|      |___ myID
|              |___ friendID1
|      |___ friendID1
|              |___ myID

3 个答案:

答案 0 :(得分:2)

由于实际的结构不清楚,让我们采用像这样的标准结构

  "users"
    "user_0"
      "friends"
        "user_1" : true,
        "user_2" : true,
        "user_3" : true
    "user_1" 
      "friends"
        "user_0" : true,
        "user_2" : true
    "user_2"
      "friends"
        "user_0" : true,
        "user_1" : true,
        "user_3" : true
    "user_3"
      "friends"
        "user_0" : true,
        "user_2" : true

如您所见,用户0是user_1,user_2和user_3的朋友,同样在他们的节点中,这些用户是user_0的朋友。

如果我们想要保留这个结构,那么找到两个用户共同朋友的交集非常容易。

假设我们想要找到user_0和user_2有哪些朋友的共同点。看看我们发现它的结构

user_1
user_3

我们如何在代码中执行此操作?

let user1FriendsRef = self.ref.child("users").child("user_0").child("friends")
let user2FriendsRef = self.ref.child("users").child("user_2").child("friends")

user1FriendsRef.observeSingleEvent(of: .value, with: { user1Snapshot in
    let user1FriendsArray = user1Snapshot.children.map { ($0 as! DataSnapshot).key }
    let user1FriendsSet = Set(user1FriendsArray)

    user2FriendsRef.observeSingleEvent(of: .value, with: { user2Snapshot in
        let user2FriendsArray = user2Snapshot.children.map { ($0 as! DataSnapshot).key }
        let user2FriendsSet = Set(user2FriendsArray)

        let mutualFriends = user1FriendsSet.intersection(user2FriendsSet).sorted()
        print(mutualFriends)
        print(mutualFriends.count)
    })
})

以下是代码的工作原理:我们首先引用我们要比较的两个用户朋友列表

使用observeSingleEvent,读取第一个用户好友列表,并将键(user_1,user_2等)存储在一个数组中。这是我的映射(迭代)每个键:值对来捕获密钥。该数组将转换为Set var。

我们对第二个用户做同样的事情 - 注意到我们在第一个关闭中做到这一点非常重要,因此我们保证第一个用户的结果是完整的。这些结果被映射到一个数组,并被制作成一个Set。

然后,利用Set的交集功能然后打印共同的朋友(已排序)

的魔力
["user_1", "user_3"]
2

答案 1 :(得分:1)

如果您在问题中发布数据库结构,那将会有很大帮助。

我认为它看起来像这样:

root/
|___ users/
|      |___ userID1
|              |___ name : user_name
|              |___ email : user_email
|              |___ picUrl : user_picture_url
|              |___ friends
|                       |___ userID2 : true                    
|                       |___ userID3 : true
|                        ...

我在下面的代码中添加了很多评论,以便您更轻松地查看每一步。

所以,这就是你编写fetchMutualFriends方法的方法:

    func fetchMutualFriends(userID: String) {

         // Use a guard statement here to make sure your current user object is not nil

        guard let currentUserID = Auth.auth().currentUser?.uid else {
             return
        }

        // Create two arrays to store the two friend lists:

        var friendListA = [String]()
        var friendListB = [String]()

        // Create a dispatch group:

        let dispatchGroup = DispatchGroup()

        // Enter the dispatch group

        dispatchGroup.enter()

        // Add the observers:

        // Depending on your database structure, you may want to adjust the references below:

        Database.database().reference().child("users").child(currentUserID).child("friends").child(userID).observeSingleEvent(of: .value, with: { [weak self] (snapshot : DataSnapshot) in

                      // Iterate through all the children:    

                      for child in snapshot.children.allObjects as! [DataSnapshot] {
                          // Add the user ID to the array:
                           self?.friendListA.append(child.key)
                      })

                      if snapshot.childrenCount == 0 {
                           // TODO: Handle the case when there is no friend in the friend list.
                      }

                     // Leave the dispatch group    

                     dispatchGroup.leave()
        })


        dispatchGroup.enter()


        Database.database().reference().child("users").child(userID).child("friends").child(currentUserID).observeSingleEvent(of: .value, with: { (snapshot : DataSnapshot) in

                     // Iterate through all the children:    

                      for child in snapshot.children.allObjects as! [DataSnapshot] {
                          // Add the user ID to the array:
                           self?.friendListB.append(child.key)
                      })

                      if snapshot.childrenCount == 0 {
                           // TODO: Handle the case when there is no friend in the friend list.
                      }

                     // Leave the dispatch group    

                     dispatchGroup.leave()
       })

      // Notify the dispatch group:

      dispatchGroup.notify(queue: DispatchQueue.main, execute: {

               // Now that both completion blocks (from your two observers) ran, you can compare the two friend lists and see if they have any friends in common:

               let commonFriendsArray  = friendListA.filter { friendListB.contains($0) }

               // Do whatever you want with the common friends list :)

        })


   }

答案 2 :(得分:0)

您必须使用 numChildren()函数,该函数返回DataSnapshot的子属性数。 假设我们在数据库中有以下数据:

{
  "name": {
    "first": "Ada",
    "last": "Lovelace"
  }
}

如果我想知道姓名的孩子数量,例如:

var b = snapshot.child("name").numChildren(); // 2 ("first", "last")

如果我想知道第一个孩子的数量,例如:

var c = snapshot.child("name/first").numChildren(); // 0

希望它会指导你。