简体   繁体   中英

How to update Array field?

Im using Firebase Firestore and want to update an array field under a userprofile with the latest chat thread's id.. Im guessing that I have to pull the entire array (if it exists) from the chat node under that user, then I need to append the new id (if it doesnt exist) and update the array.. It works when theres only 1 value in the array then it fails after that with the following error:

Transaction failed: { Error: Cannot convert an array value in an array value. at /user_code/node_modules/firebase-admin/node_modules/grpc/src/node/src/client.js:554:15 code: 3, metadata: Metadata { _internal_repr: {} } }

and here is my firebase cloud function, can anyone tell me where im going wrong ?

  exports.updateMessages = functions.firestore.document('messages/{messageId}/conversation/{msgkey}').onCreate(  (event) => {
    /// console.log('function started');
    const messagePayload = event.data.data();
    const userA = messagePayload.userA;
    const userB = messagePayload.userB;     
    // console.log("userA " + userA);
    // console.log("userB " + userB);  
    // console.log("messagePayload " + JSON.stringify(messagePayload, null, 2) );    

  const sfDocRef = admin.firestore().doc(`users/${userB}`);

  return admin.firestore().runTransaction( (transaction) => {

      return transaction.get(sfDocRef).then( (sfDoc) => {

          const array = [];
          array.push(...[event.params.messageId, sfDoc.get('chats') ]);

          transaction.update(sfDocRef, { chats: array } ); 

      });
  }).then( () => {
      console.log("Transaction successfully committed!");
  }).catch( (error) => {
      console.log("Transaction failed: ", error);
  });  

  });

You're nesting arrays in your code here:

const array = [];
array.push(...[event.params.messageId, sfDoc.get('chats') ]);

This leads to an array with two values, the first one being the new messageId and the second value contains an array all of your previous values, eg

[ "new message id", ["previous id", "older id"] ]

This type of nested array is something that Firestore (apparently) doesn't allow to be stored.

The solution is simple:

const array = [event.params.messageId, ...sfDoc.get('chats')];

The fact that you have to first load the array to then add a single element to it is one of reasons Firebasers recommend not storing data in arrays. Your current data looks like it'd be better off as a set, as shown in the Firestore documenation :

{
  "new message id": true, 
  "previous id": true, 
  "older id": true
}

That way adding a chat ID is as simple as:

sfDocRef.update({ "chats."+event.params.messageId, true })

I have looked further into the matter, and I would follow the advice that Frank gave you in his post; allocate the data in collections rather than with arrays as they have greater versatility for Firebase 1 . Researching under the examples listed in the Firebase website looking for anything related to a chat, I've found the data structure and code for messages that are used by Firechat as they might be of use for you.

In the source code, they use a collection for the their message-id -userId pair with the following topology 2 : 示例的拓扑

The exact way how the saving is executed at the repository is 3 : 追加句子

It executes an append of the message into the Room-id collection. Instead of this structure, you could use an userID - messageID pair as it might fit you better.

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