如何加快此Firestore查询循环的性能?将电话联系人列表与Firestore数据库进行比较以进行匹配

Jef*_*ett 3 performance loops contacts google-cloud-firestore

我正在将用户手机中的联系人电子邮件列表与我的Firestore数据库中的用户电子邮件列表进行比较,然后创建新的"contactsInApp"列表.

首先,我从firestore数据库中获取整个用户集合.然后,对于每个用户,我创建一个forEach循环,检查我的电话联系人列表中的每个联系人是否匹配.如果匹配,则会创建一个新的"androidContactsInApp"列表.当有少量用户时它可以正常工作,但是当我用5,000个用户测试时,它需要更长的时间 - 大约30秒.我认为firestore应该很好地扩展,所以想知道我的代码是否有问题.

这是我的代码:

fsDB.collection("users")
                .get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
            @Override
            public void onSuccess(QuerySnapshot documentSnapshots) {
                for (DocumentSnapshot document : documentSnapshots) {

                    String userEmail = document.get("email").toString();

                    for (UserInfoForRequest android_contact: arrayListAndroidContacts) {
                        String isEmailInDatabase = android_contact.getUserEmail();
                        String trimmedEmail = isEmailInDatabase.trim();
                        if (userEmail.equals(trimmedEmail)) {
                            String userID = document.getId();


                            UserInfoForRequest android_contact2 = new UserInfoForRequest();
                            android_contact2.setUserName(document.get("username").toString());
                            android_contact2.setUserEmail(userEmail);
                            android_contact2.setCurrentUID(currentUID);
                            android_contact2.setContactsUID(userID);
                            arrayListAndroidContactsInApp.add(android_contact2);

                        }


                    }

                }
                adapterWithApp.notifyDataSetChanged();
                adapterNoApp.notifyDataSetChanged();
            }
        });
Run Code Online (Sandbox Code Playgroud)

我也试过反转循环.这样做,我在我的电话联系人列表中获得每个联系人,并且我为每个电话联系人执行查询.这意味着我没有下载整个用户集合.这种方法要慢很多 - 慢得多.我认为这是因为我执行单独的个别查询.这是我的代码:

        for (final UserInfoForRequest android_contact: arrayListAndroidContacts) {

            String contactsEmail = android_contact.getUserEmail();
            String trimmedEmail = contactsEmail.trim();

            fsDB.collection("users").whereEqualTo("email", trimmedEmail).get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot documentSnapshots) {

                    if (documentSnapshots.isEmpty()) {
                        Log.d("FOUNDEMAIL", " document is empty ");

                    }
                    else {

                        List list = documentSnapshots.getDocuments();

                        DocumentSnapshot doc = (DocumentSnapshot) list.get(0);

                        UserInfoForRequest android_contact2 = new UserInfoForRequest();
                        android_contact2.setUserName(doc.get("username").toString());
                        android_contact2.setUserEmail(doc.get("email").toString());
                        android_contact2.setCurrentUID(currentUID);
                        android_contact2.setContactsUID(doc.getId());
                        arrayListAndroidContactsInApp.add(android_contact2);


                        adapterWithApp.notifyDataSetChanged();
                        adapterNoApp.notifyDataSetChanged();

                    }
                }
            })
Run Code Online (Sandbox Code Playgroud)

编辑:好的,所以我做了一些测试.当我使用"Snapshot Listener"而不是使用.get时,我能够节省4秒来检索文档快照,从27.5秒减少到23.5秒.我还发现循环本身只需要4秒钟 - 文档检索需要19秒.

然后,我删除了5,000个用户,并对1,000个用户进行了测试.1,000个用户的加载时间是6.5秒,循环本身是.1秒.这只是firebase需要解决的问题,以加快速度吗?

Jef*_*ett 5

我想出了一种大大加快搜索速度的方法.

代码没有问题.问题是它对于客户端设备而言过于密集.

相反,我使用了云功能,因此具有更强大功能的服务器本身可以处理循环.

  1. 获取设备上的联系人列表.
  2. 将联系人列表(电子邮件或电话号码)发送到firestore数据库中的特定文档.即. fsDB.doc("users/UID/device_contacts);
  3. 创建一个在创建该文档时激活的云功能... exports.NewContactList = admin.firestore().doc('users/${UID}/device_contacts);
  4. 该功能读取文档,并查找其电子邮件或电话号码==电话或电子邮件在文档中的任何"用户".
  5. 然后它将这些用户放入一个新文档 - users/UID/suggestedFriends
  6. 然后,客户端设备从创建的文档中读取建议的朋友列表.

此过程仍需要时间,但仅在您第一次创建建议列表时.它也发生在后台,因此设备不会停滞.然后我还创建了一个功能,当新用户添加到数据库或用户手机中有新联系人时,该功能会更新列表.

编辑

我写的功能......

exports.createdFriendListTest =     functions.firestore.document('users/{userID}/device_contacts/device_contacts').onCreate(event => {
console.log('test worked... function called after creating doc 1st time.');

const userID = event.params.userID;
const docWithContacts = event.data.data();
console.log(docWithContacts);

var promises = []; // to hold promises within the keyList.forEach loop.
const keyList = Object.keys(docWithContacts);
keyList.forEach(key => {

    var promise = admin.firestore().collection('users').where('email', '==', key).get().then(querySnapshot =>{
        console.log('querySnapshot obtained');
         if (querySnapshot.empty) {
             console.log('there is no user ', key, ' within database.');
             return true;
         } else {
             console.log('user, ', key, ' exists in database');
             querySnapshot.docs.forEach(docSnap => { 

                const userExistID = docSnap.id;
                console.log('that user ID is ', userExistID);

                const userData = docSnap.data();
                console.log('user Data', userData);

                const SuggestFriend = admin.firestore().doc(`users/${userID}/suggested_friends/${userExistID}`).set(userData);
                return SuggestFriend.then(result => {
                    console.log('suggested friend added');
                    return true;
                })
            })
         }
    })
    promises.push(promise);
})
return Promise.all(promises);
});
Run Code Online (Sandbox Code Playgroud)