3

I am new to Firebase and I have to create a chat system. I found that the doc structure should be nested e.g if a person sends a message, a new doc with its id will be created in the main collection and then a new collection will be added to the doc. now each doc in that nested collection will be considered as a message obj.

a rough sketch of how the new message in the nested document will be added but the problem is when there is no doc with UI exist or no collection in that doc exist

firestore().collection("chatBox").doc(uid).collection("message").add( { text: "this is my first message", user: {_id:356}, avatar: "link of avatar", name: "john", createdAt: new Date().getTime() } )

  const sendMessage = async (messages = []) => {
  const msg = messages[0];

    const id = msg.user?._id?.toString();
    const collectionRef = firestore().collection(CHATBOX);
    const doc = collectionRef.doc(id);
    const docExists = await doc.get().then(function (doc) {
      return doc.exists;
    });
    if (docExists) {
      const collection = doc.collection(MESSAGES);
     const isCollectionEmpty = collection.get().then(col => {
        return col.empty;
      });
      if (isCollectionEmpty) doc.set({id: MESSAGES});//creating new collection
      else collection.add({...msg, createdAt: new Date().getTime()});//inserting doc if collection exist
    } else {
      collectionRef.add(id);// creating doc in main collection
    }
};
Jatin Bhuva
  • 1,301
  • 1
  • 4
  • 22
  • i found solution. actually for checking if document exist and then creating a document is not the right approach. what we need to do is simply use .add to add document. what firebase does is that it identifies if that document exist it doesn't create new and if there is not document with such name it creates a new document with the name passed to it as id – sana arshed Mar 29 '23 at 07:48

1 Answers1

2

The ability to create a document only if it does not exist can be done using the following Transaction. Here, the createDocIfNotExist method creates the document with the given data, only if it does not already exist. It returns a Promise<boolean> indicating whether the document was freshly created or not.

async createDocIfNotExist(docRef, initData) {
  return docRef
    .firestore
    .runTransaction((transaction) => {
      const docSnap = await transaction.get(docRef);
      if (docSnap.exists)
        return false; // exists already

      transaction.set(docRef, initData);
      return true; // was created
    });
}

Applying this to your code then gives:

const sendMessage = async (messages = []) => {
  const msg = messages[0];

  const msgUserId = msg.user!._id!.toString(); // id renamed, consider using senderId/recipientId instead

  const chatboxColRef = firestore().collection(CHATBOX); // collectionRef renamed
  const userChatboxDocRef = chatboxColRef.doc(msgUserId); // doc renamed

  const isNewChatbox = await createDocIfNotExist(
    userChatboxDocRef,
    { id: msgUserId }
  );

  const userChatboxMessagesColRef = userChatboxDocRef.collection(MESSAGES); // collection renamed

  return userChatboxMessagesColRef
    .add({
      ...msg,
      createdAt: new Date().getTime() // consider using firebase.firestore.FieldValue.serverTimestamp() instead
    });
};

This can be further reduced to:

const sendMessage = async (messages = []) => {
  const msg = messages[0];

  const msgUserId = msg.user!._id!.toString();

  const userChatboxDocRef = firestore()
    .collection(CHATBOX);
    .doc(msgUserId);

  await createDocIfNotExist(
    userChatboxDocRef,
    { id: msgUserId }
  );

  return userChatboxDocRef
    .collection(MESSAGES)
    .add({
      ...msg,
      createdAt: new Date().getTime()
    });
};

Note: Avoid using the variable name doc as it is ambiguous and could be an instance of DocumentData, DocumentReference, or DocumentSnapshot (at minimum, use docData, docRef and docSnap/docSnapshot respectively). Similarly, use colRef for a CollectionReference and qSnap/querySnap for QuerySnapshot objects.

samthecodingman
  • 23,122
  • 4
  • 30
  • 54