Javascript 如何更新";“对象数组”;和Firestore一起?
我目前正在尝试Firestore,但我遇到了一个非常简单的问题:“更新数组(也称为子文档)” 我的数据库结构非常简单。例如:Javascript 如何更新";“对象数组”;和Firestore一起?,javascript,arrays,object,firebase,google-cloud-firestore,Javascript,Arrays,Object,Firebase,Google Cloud Firestore,我目前正在尝试Firestore,但我遇到了一个非常简单的问题:“更新数组(也称为子文档)” 我的数据库结构非常简单。例如: proprietary: "John Doe", sharedWith: [ {who: "first@test.com", when:timestamp}, {who: "another@test.com", when:timestamp}, ], 我正在尝试(没有成功)将新记录推送到shareWith对象数组中 我试过: // With SE
proprietary: "John Doe",
sharedWith:
[
{who: "first@test.com", when:timestamp},
{who: "another@test.com", when:timestamp},
],
我正在尝试(没有成功)将新记录推送到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() }] })
都不管用。这些查询覆盖了我的数组
答案可能很简单,但我找不到它…编辑2018年8月13日:现在在Cloud Firestore中支持本机阵列操作。见下文
目前无法更新Cloud Firestore中的单个数组元素(或添加/删除单个元素) 此代码如下:
firebase.firestore()
.collection('proprietary')
.doc(docID)
.set(
{ sharedWith: [{ who: "third@test.com", when: new Date() }] },
{ merge: true }
)
这意味着将文档设置为propertial/docID
,以便sharedWith=[{who:third@test.com“,when:new Date()}
但不影响任何现有的文档属性。这与您提供的update()
调用非常相似,但是set()
调用创建文档(如果文档不存在),而更新()调用将失败
所以你有两个选择来实现你想要的
选项1-设置整个阵列
使用数组的全部内容调用set()
选项2-使用子集合
您可以将与主文档的子集合共享。然后
添加单个项目将如下所示:
firebase.firestore()
.collection('proprietary')
.doc(docID)
.collection('sharedWith')
.add({ who: "third@test.com", when: new Date() })
proprietary: "John Doe"
sharedWith:{
whoEmail1: {when: timestamp},
whoEmail2: {when: timestamp}
}
当然,这会带来新的限制。您将无法查询
基于共享对象的文档,您也无法
在一次操作中获取文档和所有与
数据共享的。除了上面提到的答案。这样就可以了。
使用Angular 5和AngularFire2。或使用firebase.firestore()而不是this.afs
// say you have have the following object and
// database structure as you mentioned in your post
data = { who: "third@test.com", when: new Date() };
...othercode
addSharedWith(data) {
const postDocRef = this.afs.collection('posts').doc('docID');
postDocRef.subscribe( post => {
// Grab the existing sharedWith Array
// If post.sharedWith doesn`t exsit initiated with empty array
const foo = { 'sharedWith' : post.sharedWith || []};
// Grab the existing sharedWith Array
foo['sharedWith'].push(data);
// pass updated to fireStore
postsDocRef.update(foo);
// using .set() will overwrite everything
// .update will only update existing values,
// so we initiated sharedWith with empty array
});
}
您可以使用事务()获取数组,推送它,然后更新文档:
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);
});
在此基础上,还有一个第三选项,它让我的事情变得更简单,那就是使用谷歌所谓的地图,它本质上是一本字典
我认为字典更适合您所描述的用例。我通常使用数组来处理实际上没有太多更新的内容,因此它们或多或少都是静态的。但是对于需要大量编写的内容,特别是需要为链接到数据库中其他内容的字段更新的值,字典被证明是非常有用的易于维护和使用
因此,对于您的特定情况,DB结构如下所示:
firebase.firestore()
.collection('proprietary')
.doc(docID)
.collection('sharedWith')
.add({ who: "third@test.com", when: new Date() })
proprietary: "John Doe"
sharedWith:{
whoEmail1: {when: timestamp},
whoEmail2: {when: timestamp}
}
这将允许您执行以下操作:
var whoEmail = 'first@test.com';
var sharedObject = {};
sharedObject['sharedWith.' + whoEmail + '.when'] = new Date();
sharedObject['merge'] = true;
firebase.firestore()
.collection('proprietary')
.doc(docID)
.update(sharedObject);
将对象定义为变量的原因是使用'sharedWith.+whoEmail+'。当在set方法中直接使用“
时,至少在Node.js云函数中使用它时,会导致错误。将John Doe视为文档而不是集合
给它一个与其他人共享的东西的集合
然后,您可以映射并查询John Doe与其他人共享的并行things集合中的共享内容
proprietary: "John Doe"(a document)
things(collection of John's things documents)
thingsSharedWithOthers(collection of John's things being shared with others):
[thingId]:
{who: "first@test.com", when:timestamp}
{who: "another@test.com", when:timestamp}
then set thingsSharedWithOthers
firebase.firestore()
.collection('thingsSharedWithOthers')
.set(
{ [thingId]:{ who: "third@test.com", when: new Date() } },
{ merge: true }
)
Firestore现在有两个函数,允许您在不重新写入整个内容的情况下更新数组
链接:,特别是
更新数组中的元素
如果文档包含数组字段,则可以使用arrayUnion()和
arrayRemove()用于添加和删除元素。arrayUnion()用于添加元素
指向数组,但仅指向尚未存在的元素。arrayRemove()
删除每个给定元素的所有实例
很抱歉,派对迟到了,但Firestore早在2018年8月就解决了这个问题,所以如果您还在这里寻找,那么所有关于阵列的问题都已经解决了
array包含、arrayRemove、arrayUnion,用于检查、删除和更新阵列。希望对您有所帮助。如果有人正在寻找Java firestore sdk解决方案以在数组字段中添加项:
List<String> list = java.util.Arrays.asList("A", "B");
Object[] fieldsToUpdate = list.toArray();
DocumentReference docRef = getCollection().document("docId");
docRef.update(fieldName, FieldValue.arrayUnion(fieldsToUpdate));
List List=java.util.Arrays.asList(“A”、“B”);
Object[]fieldsToUpdate=list.toArray();
DocumentReference docRef=getCollection().document(“docId”);
docRef.update(fieldName,FieldValue.arrayUnion(fieldsToUpdate));
要从数组中删除项目,请执行以下操作:FieldValue.arrayRemove()
以下是Firestore文档中的最新示例:
firebase.firestore.FieldValue
var washingtonRef=db.collection(“cities”).doc(“DC”);
//以原子方式将新区域添加到“区域”数组字段。
washingtonRef.update({
地区:firebase.firestore.FieldValue.arrayUnion(“弗吉尼亚州大城市”)
});
//以原子方式从“区域”数组字段中删除区域。
washingtonRef.update({
地区:firebase.firestore.FieldValue.arrayRemove(“东海岸”)
});
addToCart(docId:string,prodId:string):承诺{
返回此.baseAngularFirestore.collection('carts').doc(docId).update({
产品:
firestore.FieldValue.arrayUnion({
productId:prodId,
数量:1
}),
});
}
我们可以使用arrayUnion({})
方法来实现这一点
试试这个:
collectionRef.doc(ID).更新({
与管理员共享:admin.firestore.FieldValue.arrayUnion({
谁∶first@test.com",
时间:新日期()
})
});
文档可以在此处找到:如果您想更新firebase文档中的数组。
你可以这样做
var documentRef = db.collection("Your collection name").doc("Your doc name")
documentRef.update({
yourArrayName: firebase.firestore.FieldValue.arrayUnion("The Value you want to enter")});
#编辑(添加说明:))
假设您有一个数组要更新现有firestore文档字段。您可以使用set(yourData,{merge:true})
passing setOptions(set函数中的第二个参数)和{merge:true}
来合并更改,而不是覆盖。以下是官方文档对此的说明
一个选项对象,用于配置DocumentReference、WriteBatch和Tr中set()调用的行为