2017-11-10 17 views
1

私はFirestoreデータベース内のユーザーの電子メールのリストとユーザーの電話の連絡先の電子メールのリストを比較してから、「contactsInApp」の新しいリストを作成します。このFirestoreクエリループのパフォーマンスをどのように高速化できますか?電話連絡先リストをFirestoreデータベースと照合する

まず、Firestoreデータベースのユーザー全員を取得します。その後、各ユーザーごとにforEachループを作成し、私の電話連絡先リスト内の各連絡先を一致するかどうかチェックします。一致するものがあれば、 "androidContactsInApp"の新しいリストを作成します。少人数のユーザーでもうまく動作しますが、5,000ユーザーでテストした場合、30秒ほどという時間がかかります。私は、ファイアストアがうまくスケールされると考えていたので、自分のコードに問題があるかどうか疑問に思っていました。私はまた、ループを反転しようとしている

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(); 
      } 
     }); 

は、ここに私のコードです。そうすることで、私は各連絡先を私の電話連絡先一覧に入れ、各電話連絡先の問い合わせを実行します。これは私がユーザーのコレクション全体をダウンロードしていないことを意味します。この方法はずっと遅く、多くの人が遅くなります。私は別々の個別のクエリを実行するためだと思います。ここに私のコードは次のとおりです。

 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(); 

        } 
       } 
      }) 

編集:[OK]をので、私はいくつかのテストをしました。 .getを使用する代わりに "Snapshot Listener"を使用した場合、27.5秒から23.5秒に短縮されたドキュメントスナップショットを取得するのに4秒間を節約できました。また、ループ自体が4秒しかかかっていないことが判明しました。文書の取得には19時間かかります。

その後、5,000人のユーザーを削除し、1,000人のユーザーでテストしました。 1,000人のユーザーの読み込み時間は6.5秒で、ループ自体は6.5秒です。 1秒。このことをスピードアップするためには、ファイアーベースで対処する必要があるのは単なる問題ですか?

+0

こんにちは@Jeffは、あなたの検索を高速化することができます。どんな解決策ですか? –

+1

はい、私は以下の答えを投稿します、ありがとう。 –

答えて

3

私は検索を大幅に高速化する方法を考え出しました。

コードに問題はありません。問題は、それがクライアントデバイスには集中的すぎるということです。

代わりに、クラウド機能を使用しました。そのため、より強力な機能を持つサーバー自体がループを処理します。

  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. 次に、クライアントデバイスは、作成されたドキュメントから推奨されるFriendsのリストを読み取ります。

このプロセスにはまだ時間がかかりますが、提案されたリストを初めて作成するときだけです。バックグラウンドでも発生するため、デバイスは停止しません。また、新しいユーザーがデータベースに追加されたとき、またはユーザーの電話に新しい連絡先があるときにリストを更新する関数を作成しました。

EDIT

私が書いた機能...

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); 
}); 
+0

こんにちは@ジェフ。答えをありがとう。あなたは、私たちの多くはJavaの背景から、あなたが使用した雲の機能を共有することができますか?node.jsをあまり知らない。 –

+1

こんにちはKarandeepさんが投稿しました。 –

+0

ありがとうございました!これがどれくらい速いかを覚えていますか? –

関連する問題