Java 如何将子集合添加到 Firebase Cloud Firestore 中的文档
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47514419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add subcollection to a document in Firebase Cloud Firestore
提问by rgoncalv
The documentation does not have any examples on how to add a subcollection to a document. I know how to add document to a collection and how to add data to a document, but how do I add a collection (subcollection) to a document?
该文档没有关于如何将子集合添加到文档的任何示例。我知道如何将文档添加到集合以及如何将数据添加到文档,但如何将集合(子集合)添加到文档?
Shouldn't there be some method like this:
不应该有这样的方法:
dbRef.document("example").addCollection("subCollection")
回答by Alex Mamo
Assuming we have a chat application which has a database structure that looks similar to this:
假设我们有一个聊天应用程序,它的数据库结构类似于:
To write a subCollection
in a document, please use the following code:
要subCollection
在文档中写入 a ,请使用以下代码:
DocumentReference messageRef = db
.collection("rooms").document("roomA")
.collection("messages").document("message1");
If you want to create messages
collection and call addDocument() 1000 times will be expensive for sure, but this is how Firestore works. You can switch to Firebase Realtime Database if you want, where the number of writes doesn't matter. But regarding Supported Data Typesin Firestore, in fact you can use an array because is suppoerted. In Firebase Realtime databaseyou could also use an array
, but this is which is an anti-pattern. One of the many reasons Firebase recommends against using arrays is that it makes the security rules impossible to write.
如果您想创建messages
集合并调用 addDocument() 1000 次肯定会很昂贵,但这就是 Firestore 的工作方式。如果需要,您可以切换到 Firebase 实时数据库,其中写入次数无关紧要。但是关于Firestore 中支持的数据类型,实际上您可以使用数组,因为它支持。在Firebase 实时数据库中,您也可以使用array
,但这是一种反模式。Firebase 建议不要使用数组的众多原因之一是它使安全规则无法编写。
Cloud Firestore can store arrays, it does not support querying array members or updating single array elements. However, you can still model this kind of data by leveraging the other capabilities of Cloud Firestore. Hereis the documentation where is very good explained.
Cloud Firestore 可以存储数组,它不支持查询数组成员或更新单个数组元素。但是,您仍然可以利用 Cloud Firestore 的其他功能对此类数据进行建模。这里是很好解释的文档。
You also cannot create a subcollection with 1000 messages and add all of them to the database and in the same time to consider a single record. It will be considered one write operation for every message. In total 1000 operations. The picture above does not show how to retrieve data, it shows a database structure in which you have something like this:
您也不能创建一个包含 1000 条消息的子集合并将它们全部添加到数据库中,同时考虑单个记录。对于每条消息,它将被视为一次写入操作。总共 1000 次操作。上图没有显示如何检索数据,它显示了一个数据库结构,其中包含以下内容:
collection -> document -> subCollection -> document
回答by Thomas David Kehoe
Here's my code:
这是我的代码:
firebase.firestore().collection($scope.longLanguage + 'Words').doc($scope.word).set(wordData)
.then(function() {
console.log("Collection added to Firestore!");
var promises = [];
promises.push(firebase.firestore().collection($scope.longLanguage + 'Words').doc($scope.word).collection('AudioSources').doc($scope.accentDialect).set(accentDialectObject));
promises.push(firebase.firestore().collection($scope.longLanguage + 'Words').doc($scope.word).collection('FunFacts').doc($scope.longLanguage).set(funFactObject));
promises.push(firebase.firestore().collection($scope.longLanguage + 'Words').doc($scope.word).collection('Translations').doc($scope.translationLongLanguage).set(translationObject));
Promise.all(promises).then(function() {
console.log("All subcollections were added!");
})
.catch(function(error){
console.log("Error adding subcollections to Firestore: " + error);
});
})
.catch(function(error){
console.log("Error adding document to Firestore: " + error);
});
This makes a collection EnglishWords
, which has a document of
. The document of
has three subcollections: AudioSources
(recordings of the word in American and British accents), FunFacts
, and Translations
. The subcollection Translations
has one document: Spanish
. The Spanish
document has three key-value pairs, telling you that 'de' is the Spanish translation of 'of'.
这将创建一个EnglishWords
包含文档的集合of
。该文档of
包含三个子集:(AudioSources
美国和英国口音的单词录音)FunFacts
、 和Translations
。该子集合Translations
有一个文档:Spanish
. 该Spanish
文档具有三个键值对,告诉您“de”是“of”的西班牙语翻译。
The first line of the code creates the collection EnglishWords
. We wait for the promise to resolve with .then
, and then we create the three subcollections. Promise.all
tells us when all three subcollections are set.
代码的第一行创建了集合EnglishWords
。我们等待 Promise 解决.then
,然后我们创建三个子集合。Promise.all
告诉我们何时设置所有三个子集合。
IMHO, I use arrays in Firestore when the entire array is uploaded and downloaded together, i.e., I don't need to access individual elements. For example, an array of the letters of the word 'of' would be ['o', 'f']
. The user can ask, "How do I spell 'of'?" The user isn't going to ask, "What's the second letter in 'of'?"
恕我直言,当整个数组一起上传和下载时,我在 Firestore 中使用数组,即,我不需要访问单个元素。例如,单词 'of' 的字母数组将是['o', 'f']
. 用户可以问,“我如何拼写‘of’?” 用户不会问,“'of' 中的第二个字母是什么?”
I use collections when I need to access individual elements, a.k.a. documents. With the older Firebase Realtime Database, I had to download arrays and then iterate through the arrays with forEach
to get the element I wanted. This was a lot of code, and with a deep data structure and/or large arrays I was downloading tons of data that I didn't need, and slowing my app running forEach
loops on large arrays. Firestore puts the iterators in the database, on their end, so that I can request a single element and it sends me just that element, saving me bandwidth and making my app run faster. This might not matter for a web app, if your computer has a broadband connection, but for mobile apps with poor data connections and slow devices this is important.
当我需要访问单个元素(也就是文档)时,我会使用集合。使用较旧的 Firebase 实时数据库,我必须下载数组,然后遍历数组forEach
以获取我想要的元素。这是大量代码,并且具有深层数据结构和/或大型数组,我正在下载大量不需要的数据,并减慢我的应用程序forEach
在大型数组上运行的循环。Firestore 将迭代器放在数据库的末尾,这样我就可以请求一个元素,它只向我发送那个元素,从而节省了我的带宽并使我的应用程序运行得更快。如果您的计算机有宽带连接,这对于网络应用程序可能无关紧要,但对于数据连接较差且设备速度较慢的移动应用程序,这很重要。
回答by Gene Bo
Here's a variation where the subcollection is storing ID values at the collection level, rather than within a document where the subcollection is a field there with additional data.
这是一个变体,其中子集合在集合级别存储 ID 值,而不是在子集合是包含附加数据的字段的文档中。
This is useful for connecting a 1-to-Many ID mappingw/out having to drill through an additional document:
这对于连接1 对多 ID 映射非常有用,而不必钻取额外的文档:
function fireAddStudentToClassroom(studentUserId, classroomId) {
var db = firebase.firestore();
var studentsClassroomRef =
db.collection('student_class').doc(classroomId)
.collection('students');
studentsClassroomRef
.doc(studentUserId)
.set({})
.then(function () {
console.log('Document Added ');
})
.catch(function (error) {
console.error('Error adding document: ', error);
});
}
Thanks to @Alex's answer
This answer a bit off from the original question here, where it explicitly asks for adding a collection to a document. However, after searching for a solution for this scenario and not finding any mention in docs or on SO, this post seems like a reasonable place to share the findings
这个答案与这里的原始问题有点不同,它明确要求将集合添加到文档中。然而,在为这种情况寻找解决方案后,在文档或 SO 中没有找到任何提及,这篇文章似乎是分享研究结果的合理场所
回答by Mihir Patel
too late for an answer but here is what worked for me,
回答太晚了,但这对我有用,
mFirebaseDatabaseReference?.collection("conversations")?.add(Conversation("User1"))
?.addOnSuccessListener { documentReference ->
Log.d(TAG, "DocumentSnapshot written with ID: " + documentReference.id)
mFirebaseDatabaseReference?.collection("conversations")?.document(documentReference.id)?.collection("messages")?.add(Message(edtMessage?.text.toString()))
}?.addOnFailureListener { e ->
Log.w(TAG, "Error adding document", e)
}
add success listener for adding document and use firebase generated ID for a path. Use this ID for the complete path for a new collection you want to add. I.E. - dbReference.collection('yourCollectionName').document(firebaseGeneratedID).collection('yourCollectionName').add(yourDocumentPOJO/Object)
添加用于添加文档的成功侦听器并使用 firebase 生成的 ID 作为路径。将此 ID 用于要添加的新集合的完整路径。IE - dbReference.collection('yourCollectionName').document(firebaseGeneratedID).collection('yourCollectionName').add(yourDocumentPOJO/Object)