Unity-将数据追加到Firestore中的现有文档

问题描述

如何在不覆盖相同密钥的先前数据的情况下将数据添加到Firestore?例如,我想将一个名为“ Player 1”的文档添加到“轨迹记录”集合中。我想在一个游戏中将玩家1的所有位置记录在一个文档中。换句话说,如何将数据附加到Firestore文档?

这是我用于将数据写入Firestore的代码。如何确保每次为同一用户运行此代码时,“数据”都不会被覆盖?对于如何实现这一点的任何帮助,将不胜感激:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Firebase.Firestore;
using System.Threading.Tasks;
using UnityEngine.UI;
using System.Linq;
using System.Threading;
using Firebase.Auth;

public class TrajectoryToFirebase : MonoBehaviour
{
    protected bool operationInProgress;
    protected Task previousTask;
    protected CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

    // name of the collection container that documents get stored into 
    protected string collectionPath = "Trajectory Log";
    protected string documentId = "";

    public float samplingRate = 1f;
    private System.DateTime dt;
    private Vector3 lastpos = Vector3.zero;
    private Quaternion lastrot = Quaternion.identity;

    //public GameStats gameStats;
    public Text text;

    //Boilerplate taskmanagement code made by the Firebase People
    ////////////////////////////////////////////////////////////////////////////
    class WaitForTaskCompletion : CustomYieldInstruction
    {
        Task task;
        TrajectoryToFirebase dbManager;
        protected CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

        // Create an enumerator that waits for the specified task to complete.
        public WaitForTaskCompletion(TrajectoryToFirebase dbManager,Task task)
        {
            dbManager.previousTask = task;
            dbManager.operationInProgress = true;
            this.dbManager = dbManager;
            this.task = task;
        }

        // Wait for the task to complete.
        public override bool keepWaiting
        {
            get
            {
                if (task.IsCompleted)
                {
                    dbManager.operationInProgress = false;
                    dbManager.cancellationTokenSource = new CancellationTokenSource();
                    if (task.IsFaulted)
                    {
                        string s = task.Exception.ToString();
                        Debug.Log(s);
                    }
                    return false;
                }
                return true;
            }
        }
    }

    ////////////////////////////////////////////////////////////////////////////

    //Get the instance of the Firestore database 
    protected FirebaseFirestore db
    {
        get
        {
            return FirebaseFirestore.DefaultInstance;
        }
    }

    private CollectionReference GetCollectionReference()
    {
        return db.Collection(collectionPath);
    }

    //Gets the reference to the docuement in Firstore
    //Here I am just setting the document manually to the userID of the sign in user
    private DocumentReference GetDocumentReference()
    {
       
         //documentId = FirebaseAuth.DefaultInstance.CurrentUser.UserId;

         documentId = "User 1";
      
        return GetCollectionReference().Document(documentId);
    }

    // Need function here that sends log data to firestore
    // make this so that it checks to see if the document is null,and if it is not,it appends to the previous entry
    // Firebase transaction?


    public void TrackTrajectory()
    {
        Debug.Log("Trajectory Tracker Called");

        

        if (transform.position != lastpos || transform.rotation != lastrot)
        {
            var data = new Dictionary<string,object>
            {
                {"Time",System.Math.Round(Time.time,2)},{"Pos X",System.Math.Round(transform.position.x,3)},{"Pos Y",System.Math.Round(transform.position.y,{"Pos Z",System.Math.Round(transform.position.z,{"Rot X",System.Math.Round(transform.rotation.x,{"Rot Y",System.Math.Round(transform.rotation.y,{"Rot Z",System.Math.Round(transform.rotation.z,};


            StartCoroutine(WriteDoc(GetDocumentReference(),data));
            
            Debug.Log("I recorded trajectory data");

            // append here? firestore transaction?


            lastpos = transform.position;
            lastrot = transform.rotation;
        }


    }

   
    // starts "timer" to start recording position and orientation?
    public void Start()
    {
        dt = System.DateTime.Now;
        Debug.Log(dt.ToString("yyyy-MM-dd-H-mm-ss"));
        InvokeRepeating("TrackTrajectory",0f,1f / samplingRate);
        
    }

    // ***  what does this do?

    public void readDataButton()
    {
        StartCoroutine(ReadDoc(GetDocumentReference()));
    }

    private static string DictToString(IDictionary<string,object> d)
    {
        return "{ " + d
            .Select(kv => "(" + kv.Key + "," + kv.Value + ")")
            .Aggregate("",(current,next) => current + next + ",")
            + "}";
    }

    //Writes the data 
    private IEnumerator WriteDoc(DocumentReference doc,IDictionary<string,object> data)
    {
        Task setTask = doc.SetAsync(data);
        yield return new WaitForTaskCompletion(this,setTask);
        if (!(setTask.IsFaulted || setTask.IsCanceled))
        {
            Debug.Log("Data written");
        }
        else
        {
            Debug.Log("Error");
        }
    }


    private IEnumerator ReadDoc(DocumentReference doc)
    {
        Task<DocumentSnapshot> getTask = doc.GetSnapshotAsync();
        yield return new WaitForTaskCompletion(this,getTask);
        if (!(getTask.IsFaulted || getTask.IsCanceled))
        {
            DocumentSnapshot snap = getTask.Result;

            IDictionary<string,object> resultData = snap.ToDictionary();
            text.text = DictToString(resultData);
            Debug.Log("Data read");
        }
        else
        {
            text.text = "Error";
        }
    }



}

解决方法

您必须使用UpdateAsync()而不是SetAsync()

您可以阅读here有关更新的Firebase文档

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...