【问题标题】:Unity - Appending Data to Existing Document in FirestoreUnity - 将数据附加到 Firestore 中的现有文档
【发布时间】:2020-11-30 23:11:01
【问题描述】:

如何将数据添加到 Firestore 而不会覆盖相同键的先前数据?例如,我想将一个名为“Player 1”的文档添加到集合“Trajectory Log”中。我想在一个文档中记录玩家 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, 3)},
                {"Pos Z",  System.Math.Round(transform.position.z, 3)},
                {"Rot X",  System.Math.Round(transform.rotation.x, 3)},
                {"Rot Y",  System.Math.Round(transform.rotation.y, 3)},
                {"Rot Z",  System.Math.Round(transform.rotation.z, 3)},

            };


            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";
        }
    }



}

【问题讨论】:

标签: c# firebase unity3d google-cloud-firestore


【解决方案1】:

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

您可以阅读here Firebase 更新文档

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-16
    • 2018-11-06
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    相关资源
    最近更新 更多