简体   繁体   中英

What is the most efficient firestore model for this use case?

In my app I currently have three collections:

db_contacts

Firestore-root
    |
    --- db_contacts (collection)
         |
         --- phoneNumber (document)
              |
              --- 'phone': phoneNumber

db_contacts holds a list of mobile phone that I add before head. The collection will contain about 1 million phone number later on. Currently it only holds 50,000 phoneNumber (50,000 documents).

users_contacts

Firestore-root
    |
    --- users_contacts (collection)
         |
         --- uid (document)
              |
              --- contacts (subcollection)
                   |
                   --- phoneNumberOfContact (document)
                          |
                          --- 'phone': phoneNumberOfContact

users_contacts holds all of the phone numbers of every user on my app. The app will be used by about 10,000 users each having ~500 contacts. So I will have 10,000 uid document and each have ~500 phoneNumberOfContact document inside the contacts subcollection.

users_common_contacts

Firestore-root
    |
    --- users_common_contacts (collection)
         |
         --- uid (document)
              |
              --- contacts (subcollection)
                   |
                   --- phoneNumberOfContact (document)
                          |
                          --- 'phone': phoneNumberOfContact

users_common_contacts contains the contacts a user have that are already in the db_contacts . I'm populating this collection on an event hook set on the users_contacts onWrite.

My Use Case

I need to create an extra collection, that stores the unique contacts of a user that are inside the users_common_contacts. What contacts only this user have in common with the db_contacts and that no other user have.

What I did so far, and turned out to be a mistake is the following:

users_unique_contacts

Firestore-root
    |
    --- users_unique_contacts (collection)
         |
         --- uid (document)
              |
              --- contacts (subcollection)
                   |
                   --- phoneNumberOfContact (document)
                          |
                          --- 'phone': phoneNumberOfContact

My Problem

I couldn't correctly populate this table, as there's no way to find the unique contacts of a single user. My code for populating users_unique_contacts is as follow:

exports.userCommonContactsListener =
    functions.firestore.document('users_common_contacts/{userID}/contacts/{documentID}')
        .onCreate((snap, context) => {
            const DocumentID = context.params.documentID;
            const UserID = context.params.userID;

            const uniqueContactsRef = admin.firestore().collection('users_unique_contacts').doc(UserID).collection("contacts");

            return new Promise((resolve, reject) => {

                uniqueContactsRef.where('phone', '==', DocumentID).get().then(contactSnapshot => {
                    if (contactSnapshot.size > 0) {
                        console.log(`Found Common Number in Unique ${contactSnapshot}`);
                        contactSnapshot.forEach(documentSnapshot => {
                            documentSnapshot.ref.delete();
                            console.log(`Deleted ${documentSnapshot.ref.id} as unique contact`);
                            resolve(`Deleted ${documentSnapshot.ref.id} as unique contact`);
                        });
                    } else {
                        var db_contacts = {}
                        db_contacts['phone'] = DocumentID;
                        db_contacts['timestamp'] = new Date();
                        uniqueContactsRef.doc(DocumentID).set(db_contacts, { merge: true }).then((res) => {
                            console.log(`Added ${DocumentID} as unique contact`);
                            resolve(`Added ${DocumentID} as unique contact`);
                        }).catch((err) => {
                            console.log(err);
                            reject("Error Removing Unique Contact", err);
                        });;
                    }
                });
            });

        });

The code is not working, the uniqueContactsRef.where('phone', '==', DocumentID).get() is never returning any values.

How can I go in modeling my users_unique_contacts ?

Update:

Further Explanation

What do I mean by: "I need to create an extra collection, that stores the unique contacts of a user that are inside the users_common_contacts. What contacts only this user have in common with the db_contacts and that no other user have."

Lets say db_contacts have the following numbers:

  • 111111
  • 222222
  • 333333
  • 444444
  • 555555
  • 123456

User A have in Common with db_contacts the following numbers:

  • 111111
  • 222222
  • 555555
  • 444444
  • 123456

User B have in Common with db_contacts the following numbers:

  • 111111
  • 222222
  • 333333
  • 555555

Now User A is the only one to have in common the following numbers:

  • 444444
  • 123456

Now User B is the only one to have in common the following numbers:

  • 333333

So User A 's unique numbers are:

  • 444444
  • 123456

So User B 's unique numbers are:

  • 333333

Since the db_contacts collection already contains all phone numbers of all users, you don't need to compare the uniqueness of user phone numbers with what exist in db_contacts collection, you need to check if the numbers a user has, exist or not in other user contact list. With other words, you need to check if a number is unique compared with other user contacts. So you need to get each number a user has and check if it exists in other user contact list. In this case, you should change your database schema a little bit by adding a new collection like this:

Firestore-root
   |
   --- allUsersNumbers (collection)
         |
         --- uid (document)
             |
             --- phoneNumbers (map)
                   |
                   --- phoneNumberOne: true
                   |
                   --- phoneNumberTwo: true

See, uid document now holds only a map, so it can fit in the 1MiB, which is the max size of the document. This is how your query should look like:

allUsersNumbersRef.where('phoneNumbers.searchedPhoneNumber', '==', true);

Now you only need to get the data. If the snapshot exists it means that is not unique, if doesn't exist it means that is unique. You can also store those numbers in an array if you want. So it's up to you to decide which solution is better for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM