【发布时间】: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";
}
}
}
【问题讨论】:
-
这与您之前关于该主题的问题有何不同? stackoverflow.com/questions/63349132/…如果您有其他信息,请编辑现有问题而不是创建新问题。
标签: c# firebase unity3d google-cloud-firestore