Search code examples
androidfirebasegoogle-cloud-firestoreandroid-contacts

Retrieve Contact Data From Firestore Efficiently Using A Query


My requirement is, when a user Mr.ABC install the app it will take all the contacts of the user and save to Firebase Firestore. And when another user Mr.XYZ installs the app in his device, it will take all contacts of XYZ and save to Firebase. Likewise whoever installs the app it will take the contacts and save to Firebase Firestore. Now my read operation should be, Mr.ABC will type XYZ number in EditText and in firebase, I have to look into XYZ contact details and find out ABC's number and get the name in which XYZ saved in his contact. So when ABC type XYZ number, ABC can able to find out in which name XYZ saved ABC's number. Please help me in which structure I should save the contacts in firebase and in how can I read the data. I would like to know the efficient way to do this. As I'm not good with database, helping me with exact code will be much more helpful. Please help.enter image description here

I have tried the below code but only 800 contacts are stored to Firestore instead of 2500, moreover i'm not sure the db structure I'm using is right or wrong. I have zero knowledge on DB.

    private void doUploadContactstoCloud() {
        dialog.setCancelable(false);
        dialog.setMessage("Please wait we are configuring your request ...");
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.show();
        listContacts = new ContactPresenter(this).fetchAllContacts();
        int j = listContacts.size();

        Log.d("sizejhfg",j+"");

        double size = listContacts.size();
        double ind = 0;
        Map<String, Object> contact = new HashMap<>();
        // Get a new write batch
        WriteBatch batch = db.batch();
        for (Contact con : listContacts) {
            for (int i = 0; i < con.numbers.size(); i++) {
                String number = formatnum(con.numbers.get(i).number);
                if (number != null) {
                    if (!number.equals("0") && number.length() < 5) {

                        Map<String, Object> contactnumber = new HashMap<>();
                        contactnumber.put("name", con.name);
                        contactnumber.put("number", number);
                        contact.put(number,contactnumber);
                        DocumentReference item = db.collection(tonumber).document(number);
                        batch.set(item,contactnumber);
                        ind++;
                        if(ind==500){
                            doCommit(batch);
                            batch=db.batch();
                            ind=0;
                        }
                    }
                }
            }
            //dialog.setProgress((int) (ind / size) * 100);
        }
        if(ind>0){
            doCommit(batch);
        }
        prefManager.setisContactUpload(true);
        doDismissDialog();
    }` 

Solution

  • Here is a possible answer to your question -

    Firstly, the Firestore Database structure. I will call it the db structure for now. Here is a template that might work for you -

    c- Contacts
       d- +1 9999999999 //ABC's Phone No.
          f- +1 0000000000 : XYZ's Number // XYZ's Saved Name in ABC's Contacts and his phone no.
          f- +1 1111111111 : LMN's Number // LMN's Saved Name in ABC's Contacts and his phone no.
       d- +1 0000000000 //XYZ's Phone No.
          f- +1 9999999999 : ABC's Number //ABC's Saved Name in XYZ's Contacts and his phone no.
          f- +1 1111111111 : LMN's Number // LMN's Saved Name in XYZ's Contacts and his phone no.
    

    Secondly, here is the code that I think will work for adding and querying the db -

    Map<String, Object> contacts = new HashMap<>();
    contacts.put("+1 0000000000", "XYZ's Number");
    contacts.put("+1 1111111111", "LMN's Number");
    
    db.collection("contacts").document("+1 9999999999")
            .set(contacts)
            .addOnSuccessListener(new OnSuccessListener<Void>() {
                @Override
                public void onSuccess(Void aVoid) {
                    Log.d(TAG, "DocumentSnapshot successfully written!");
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Log.w(TAG, "Error writing document", e);
                }
            });
    

    EDITED this part for a more efficient query -

    db.collections("contacts").document("+1 9999999999").get(EditTextEnteredNumber)
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                    for (QueryDocumentSnapshot snap : queryDocumentSnapshots) {
                        Log.d(TAG, snap.getId() + " => " + snap.getData());
                        TextViewContactName.setText(snap.getData());
                    }
                }
            });
    

    Hope this helps!!

    Sources