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需要解决的问题,以加快速度吗?
我想出了一种大大加快搜索速度的方法.
代码没有问题.问题是它对于客户端设备而言过于密集.
相反,我使用了云功能,因此具有更强大功能的服务器本身可以处理循环.
fsDB.doc("users/UID/device_contacts);exports.NewContactList = admin.firestore().doc('users/${UID}/device_contacts);users/UID/suggestedFriends此过程仍需要时间,但仅在您第一次创建建议列表时.它也发生在后台,因此设备不会停滞.然后我还创建了一个功能,当新用户添加到数据库或用户手机中有新联系人时,该功能会更新列表.
编辑
我写的功能......
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)