ner*_*lip 70 javascript arrays object firebase google-cloud-firestore
我正在尝试Firestore,而且我遇到了一些非常简单的事情:"更新一个数组(也就是一个子文档)".
我的DB结构非常简单.例如:
proprietary: "John Doe",
sharedWith:
[
{who: "first@test.com", when:timestamp},
{who: "another@test.com", when:timestamp},
],
Run Code Online (Sandbox Code Playgroud)
我正在尝试(没有成功)将新记录推送到shareWith
对象数组中.
我试过了:
// With SET
firebase.firestore()
.collection('proprietary')
.doc(docID)
.set(
{ sharedWith: [{ who: "third@test.com", when: new Date() }] },
{ merge: true }
)
// With UPDATE
firebase.firestore()
.collection('proprietary')
.doc(docID)
.update({ sharedWith: [{ who: "third@test.com", when: new Date() }] })
Run Code Online (Sandbox Code Playgroud)
没有用.这些查询会覆盖我的数组.
答案可能很简单,但我找不到......
谢谢
Dou*_*nte 91
Firestore现在有两个函数,允许您更新数组而无需重写整个数据.
链接:https://firebase.google.com/docs/firestore/manage-data/add-data,特别是https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array
更新数组中的元素
如果您的文档包含数组字段,则可以使用arrayUnion()和arrayRemove()来添加和删除元素.arrayUnion()向数组添加元素,但只添加元素.arrayRemove()删除每个给定元素的所有实例.
Sam*_*ern 51
编辑08/13/2018:现在支持Cloud Firestore中的本机阵列操作.请参阅下面的道格答案.
目前无法在Cloud Firestore中更新单个数组元素(或添加/删除单个元素).
这段代码在这里:
firebase.firestore()
.collection('proprietary')
.doc(docID)
.set(
{ sharedWith: [{ who: "third@test.com", when: new Date() }] },
{ merge: true }
)
Run Code Online (Sandbox Code Playgroud)
这是说,在设置文件proprietary/docID
,使得sharedWith = [{ who: "third@test.com", when: new Date() }
但是不会影响现有的文档属性.它与update()
您提供的set()
呼叫非常相似,但是如果在update()
呼叫失败时它不存在则创建文档.
所以你有两个选择来实现你想要的.
选项1 - 设置整个阵列
调用set()
数组的全部内容,这将需要首先从数据库中读取当前数据.如果您担心并发更新,则可以在事务中执行所有这些操作.
选项2 - 使用子集合
您可以sharedWith
对主文档进行子集合.然后添加单个项目将如下所示:
firebase.firestore()
.collection('proprietary')
.doc(docID)
.collection('sharedWith')
.add({ who: "third@test.com", when: new Date() })
Run Code Online (Sandbox Code Playgroud)
当然,这带来了新的局限性.您将无法根据共享对象来查询文档,也无法sharedWith
在单个操作中获取文档和所有数据.
Vee*_*ddy 25
这是 Firestore 文档中的最新示例:
firebase.firestore.FieldValue。阵列联合
var washingtonRef = db.collection("cities").doc("DC");
// Atomically add a new region to the "regions" array field.
washingtonRef.update({
regions: firebase.firestore.FieldValue.arrayUnion("greater_virginia")
});
// Atomically remove a region from the "regions" array field.
washingtonRef.update({
regions: firebase.firestore.FieldValue.arrayRemove("east_coast")
});
Run Code Online (Sandbox Code Playgroud)
小智 13
您可以使用交易(https://firebase.google.com/docs/firestore/manage-data/transactions)获取数组,将其推送到该数据,然后更新文档:
const booking = { some: "data" };
const userRef = this.db.collection("users").doc(userId);
this.db.runTransaction(transaction => {
// This code may get re-run multiple times if there are conflicts.
return transaction.get(userRef).then(doc => {
if (!doc.data().bookings) {
transaction.set({
bookings: [booking]
});
} else {
const bookings = doc.data().bookings;
bookings.push(booking);
transaction.update(userRef, { bookings: bookings });
}
});
}).then(function () {
console.log("Transaction successfully committed!");
}).catch(function (error) {
console.log("Transaction failed: ", error);
});
Run Code Online (Sandbox Code Playgroud)
抱歉,聚会迟到了,但 Firestore 早在 2018 年 8 月就解决了,所以如果您仍在寻找它,那么所有关于数组的问题都已解决。
https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html官方博文
array-contains、arrayRemove、arrayUnion 用于检查、删除和更新数组。希望能帮助到你。
以Sam Stern 的回答为基础,还有第三个选项让我更轻松,那就是使用 Google 所谓的地图,它本质上是一本字典。
我认为字典对于您描述的用例要好得多。我通常将数组用于没有真正更新太多的东西,所以它们或多或少是静态的。但是对于需要大量编写的内容,特别是需要为链接到数据库中其他内容的字段更新的值,事实证明字典更易于维护和使用。
因此,对于您的具体情况,数据库结构如下所示:
proprietary: "John Doe"
sharedWith:{
whoEmail1: {when: timestamp},
whoEmail2: {when: timestamp}
}
Run Code Online (Sandbox Code Playgroud)
这将允许您执行以下操作:
var whoEmail = 'first@test.com';
var sharedObject = {};
sharedObject['sharedWith.' + whoEmail + '.when'] = new Date();
sharedObject['merge'] = true;
firebase.firestore()
.collection('proprietary')
.doc(docID)
.update(sharedObject);
Run Code Online (Sandbox Code Playgroud)
将对象定义为变量的原因是,'sharedWith.' + whoEmail + '.when'
直接在 set 方法中使用会导致错误,至少在 Node.js 云函数中使用时如此。
#Edit(添加说明:))假设您有一个数组要用来更新现有的 firestore 文档字段。您可以使用set(yourData, {merge: true} )
传递 setOptions(set 函数中的第二个参数) 来{merge: true}
合并更改而不是覆盖。这是官方文档的相关内容
一个选项对象,用于配置 DocumentReference、WriteBatch 和 Transaction 中 set() 调用的行为。可以将这些调用配置为执行粒度合并,而不是通过提供带有 merge: true 的 SetOptions 来完全覆盖目标文档。
你可以用这个
const yourNewArray = [{who: "first@test.com", when:timestamp}
{who: "another@test.com", when:timestamp}]
collectionRef.doc(docId).set(
{
proprietary: "jhon",
sharedWith: firebase.firestore.FieldValue.arrayUnion(...yourNewArray),
},
{ merge: true },
);
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助 :)
归档时间: |
|
查看次数: |
56677 次 |
最近记录: |