Javascript Firebase:如何向不同的集合提交表单数据?
我有一张表格。表单中的一个字段是字段数组-用于可重复的字段。除此字段外,所有其他表单字段都存储在单个集合(父集合)中 父集合具有字段数组的数组,该数组保存每个重复条目的值,以存储在子集合(子集合)中 在编写firestore提交时,我试图将要提交到父集合的字段与要提交到子集合的字段分开 我的尝试如下Javascript Firebase:如何向不同的集合提交表单数据?,javascript,firebase,google-cloud-firestore,formik,Javascript,Firebase,Google Cloud Firestore,Formik,我有一张表格。表单中的一个字段是字段数组-用于可重复的字段。除此字段外,所有其他表单字段都存储在单个集合(父集合)中 父集合具有字段数组的数组,该数组保存每个重复条目的值,以存储在子集合(子集合)中 在编写firestore提交时,我试图将要提交到父集合的字段与要提交到子集合的字段分开 我的尝试如下 <Formik initialValues={{ term: "", category: [], relatedTerms: [
<Formik
initialValues={{ term: "", category: [], relatedTerms: [], }}
onSubmit={(values, { setSubmitting }) => {
setSubmitting(true);
firestore.collection("glossary").doc().set({
term: values.term,
category: values.category,
createdAt: firebase.firestore.FieldValue.serverTimestamp()
}),
firestore.collection("glossary").doc().collection('relatedTerms').doc().set({
dataType: values.dataType,
title: values.Title,
description: values.description,
})
.then(() => {
setSubmitionCompleted(true);
});
}}
注意,我在relatedTerms文档中注释了除title属性之外的所有内容,以便查看这是否有效
没有。表单仍然呈现,当我尝试按submit时,它只是挂起。控制台中不会生成任何错误消息,但会生成一条警告消息,说明:
0.chunk.js:141417警告:从submitForm()FirebaseError:调用函数WriteBatch.set()时捕获到未经处理的错误
无效数据。不支持的字段值:未定义(在字段中找到
(标题)
当我在谷歌上搜索这个时——从这里可以看出,在relatedTerm集合中定义父级文档id的方式可能有问题
我还想知道是否需要为每个集合分别定义和初始化初始值
当我尝试用控制台记录表单条目的值时,我可以看到一个值为title的对象被捕获。表单的初始值包括一个名为relatedTerms的数组(初始值:[])
也许我需要做一些事情,将该数组转换为其中的值,然后再尝试将其发送到firestore。我该怎么做
我链接的帖子将其分为两个步骤,但我太慢了,弄不清他们在做什么,或者我自己怎么做。奇怪的是,当我不尝试在firestore集合之间分割表单值时,这个问题就不会出现——如果我只使用一个文档,那么这里需要发生的任何事情都会在默认情况下完成
我不确定我想做的是否是firestore文档在本节中描述的。我注意到上面的添加数据示例显示了添加一个数组,而没有在提交之前采取任何步骤将数组中的项转换为数据类型。我不确定这是否是正确的查询行,因为如果我不尝试在集合之间分割数据,提交的结果很好
下一次尝试
安德烈亚斯的回答对我来说很简单。spread运算符在relatedTerms条目的submit方法中使用时工作
然而,这带来了下一个挑战——如何读取子集合数据。这部分内容让我感到困惑。我搞不懂
它说:
使用mobile/web无法检索集合列表
客户端库
这是否意味着我无法读取relatedTerms表中的值
在此之前,我能够读取relatedTerms数据数组,如下所示:
function useGlossaryTerms() {
const [glossaryTerms, setGlossaryTerms] = useState([])
useEffect(() => {
firebase
.firestore()
.collection("glossary")
.orderBy('term')
.onSnapshot(snapshot => {
const glossaryTerms = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data(),
}))
setGlossaryTerms(glossaryTerms)
})
}, [])
return glossaryTerms
}
然后:
虽然在我尝试提交表单时它没有生成任何错误,但它也没有在relatedTerms文档中创建名为glossaryId的条目。值的日志也不包括它
我已经看到了吉姆的答案。我不知道如何在单独的useEffect中使用我的glossaryTerm.id作为文档id来查找相关术语。每次调用
doc()
,都会生成一个对随机生成的新文档的引用。这意味着您对firestore.collection(“glossary”).doc()的第一次调用将生成一个新的ID,以及随后的调用。如果要重用文档引用,必须将其存储在变量中
const firstDocRef = firestore.collection("glossary").doc()
firstDocRef.set(...)
请稍后使用相同的变量:
const secondDocRef = firstDocRef.collection('relatedTerms').doc()
secondDocRef.set(...)
我没有足够的因果报应或任何东西来评论,所以我把我的评论放在这里
下面是用代码实现Doug解决方案的一种方法。抱歉,在advanced中出现了语法错误--我没有测试运行此代码
您可以在执行之前传递文档ID,即使提交时生成了autoID
onSubmit={(values, { setSubmitting }) => {
setSubmitting(true);
const newDocRef = firestore.collection("glossary").doc() // auto generated doc id saved here
let writeBatch = firestore.batch();
writeBatch.set(newDocRef,{
term: values.term,
definition: values.definition,
category: values.category,
context: values.context,
createdAt: firebase.firestore.FieldValue.serverTimestamp()
}),
writeBatch.set(newDocRef.collection('relatedTerms').doc(),{
dataType: values.dataType,
title: values.title,
description: values.description,
})
writeBatch.commit()
.then(() => {
setSubmitionCompleted(true);
});
}}
但是在提交完成之前不会生成第一个ref?那么-我如何才能将术语表id提供给relatedTerms集合呢?我不知道你在问什么。这里有什么不符合您的期望?我有一个表单,其中包含“术语”、“定义”和“相关术语”字段。前两个字段是字符串,在词汇表集合中作为文档提交,同时还有一个relatedTerms数组。relatedTerms是一个可重复的表单字段(用户可以提交多个字段条目)。每个词汇表都会与相关词汇表文档的id一起保存在“relatedTerms”子集合中。这些术语在一个表单中完成,但是提交处理程序需要将数据发送到不同的集合。我正试图弄清楚如何提交。我的建议有什么具体的地方没有按你期望的方式工作?您看到如何为嵌套在“词汇表”下的文档生成不同的文档ID了吗?我不理解您的建议。提交时,在术语表上生成autoID。我如何捕捉它,然后在relatedTerms字段中使用它?至于常量的格式,我知道doc id在括号内,而不是在:.doc()firstDocRef之后。我不知道如何在提交处理程序中使用这些常量。Firestore(和其他基于文档的数据库)有一些技术,相对来说,可以更好地实现您想要做的事情。如果你不喜欢技术文献,我会从这里开始:。谢谢@Cehhiro的建议。我刚看了这个40分钟的视频。虽然理论上讲的是数据的结构和存储方式,但实际上并没有回答我的问题
function useGlossaryTerms() {
const [glossaryTerms, setGlossaryTerms] = useState([])
useEffect(() => {
firebase
.firestore()
.collection("glossary")
.orderBy('term')
.onSnapshot(snapshot => {
const glossaryTerms = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data(),
}))
setGlossaryTerms(glossaryTerms)
})
}, [])
return glossaryTerms
}
{glossaryTerm.relatedTerms.map(relatedTerm => (
<Link to="" className="bodylinks" key={relatedTerm.id}>
{relatedTerm.title}
</Link> ))}
glossaryId: newDocRef.id,
...values.relatedTerms
const firstDocRef = firestore.collection("glossary").doc()
firstDocRef.set(...)
const secondDocRef = firstDocRef.collection('relatedTerms').doc()
secondDocRef.set(...)
onSubmit={(values, { setSubmitting }) => {
setSubmitting(true);
const newDocRef = firestore.collection("glossary").doc() // auto generated doc id saved here
let writeBatch = firestore.batch();
writeBatch.set(newDocRef,{
term: values.term,
definition: values.definition,
category: values.category,
context: values.context,
createdAt: firebase.firestore.FieldValue.serverTimestamp()
}),
writeBatch.set(newDocRef.collection('relatedTerms').doc(),{
dataType: values.dataType,
title: values.title,
description: values.description,
})
writeBatch.commit()
.then(() => {
setSubmitionCompleted(true);
});
}}