0

I'm currently creating an entry in the Firestore as following:

db.collection(userId).document(title).collection(subTitle).addDocument(data: [
   "key": "value"
])

I'm fetching the data as following. I understand that Firebase only allows shallow queries and I'm only looking to get the list of immediate documents (and not the sub collections):

self?.db.collection(user!.uid)
    .addSnapshotListener { documentSnapshot, error in
        guard let document = documentSnapshot else {
            print("Error fetching document: \(error!)")
            return
        }
        
        print("document", document)
        document.documents.forEach { (snapshot) in
            print("snapshot", snapshot)
            let data = snapshot.data()
            print("data", data)
        }

    }

But, I'm only getting <FIRQuerySnapshot: 0x7fba4cd2baa0> from document and there's nothing to be parsed.

I've also tried:

self?.db.collection(user!.uid).getDocuments() { (querySnapshot, err) in
    if let err = err {
        print("Error getting documents: \(err)")
    } else {
        for document in querySnapshot!.documents {
            print("\(document.documentID) => \(document.data())")
            
        }
    }
}

I get the same result as above.

However, when I create an entry as following (without the sub collection), I can retrieve the data perfectly fine:

self.db.collection(userId).document(title).setData([
    "key": "value"
])

enter image description here

The hierarchy

- First collection
   - First document
      - Second collection
         - Second document (with randomly generated ID from "addDocument")
            - Fields

What's frustrating is that even if I reference a specific document by its name, the query returns empty:

let docRef = self?.db.collection(user!.uid).document("0x6cac0720c8537467d7d2dccd9b88b8c757e10dfd3dcb8991ff71a4f8dfe1dd")

docRef!.getDocument { (document, error) in
    if let document = document, document.exists {
        let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
        print("Document data: \(dataDescription)")
    } else {
        print("Document does not exist")
    }
}
Kevvv
  • 3,655
  • 10
  • 44
  • 90
  • `userId` is an odd name for a collection. Ordinarily that would be a doc name on a "users" collection. It would be worthwhile to share a screen image or two of the hierarchy as it appears in the console. – danh May 20 '21 at 21:35
  • @danh Most of the names of the collections and documents are dynamically generated, but when I fetch the data from Firestore, only the hard coded document ("result.hash" in the picture) is fetched, which is also the one without the sub collection. Also, I chose `userId` as the name for a collection because each user will have a collection to themselves. – Kevvv May 20 '21 at 21:56
  • Your document doesn't exist which is why you can't read anything. See in the screenshot where there's Start Collection and Add Field below that? If you scroll down ( in the Firebase console ) you'll see this message *This document does not exist, it will not appear in queries or snapshots*. You know the doc doesn't exist when it's italic - that is just a placeholder that contains no data. So the *result.hash* document does exist because it's not italic. See [This Answer](https://stackoverflow.com/questions/53208658/firestore-document-subcollection-is-not-existing) – Jay May 21 '21 at 18:40
  • I am marking this as a duplicate because the issue/problem is exactly the same as the linked Question/Answer. If it's not a dup, please provide more details and we'll unmark it. – Jay May 22 '21 at 12:46
  • @Jay why was the document (result.hash) created when there was no sub collection, but didn't get created when I tried to create a sub collection at the same time? – Kevvv May 22 '21 at 13:49
  • result.hash has a value (try clicking on it) so therefore it exists and is not just a placeholder. Check the link as it's a pretty good explanation; subcollections can exist within a placeholder (the placeholder will be italic) but if there are fields or documents, THEN the placeholder document will exist (not italic, like result.hash). If it's just a placeholder, then it will not be returned in queries or getDocuments. – Jay May 22 '21 at 16:18
  • But when I create an entry using the first command in my question, fields and documents do get created. I am specifying `collection(userId)`, `document(title)`, `collection(subTitle)` as well as the fields. When I click on the last collection, I can see the `key` and `value` listed in the console. I'm not sure why it's regarding the collection I specified as a placeholder. – Kevvv May 22 '21 at 16:35
  • 1
    A document MUST contain data to exist. A collection within a document is NOT that documents data, it's a separate entity. What you're describing is a collection within a document `collection/document/collection` so the document there in the middle only has a collection, therefore it's a placeholder and doesn't exist. I think there's an overall design issue here as that trailing collection (subtitle) should actually be the documents data. Do this, you say `document(title)` but that's not a title, its a documentID, so add a field in that document called `title` and a value of some string – Jay May 23 '21 at 13:23

1 Answers1

0

You say you create a document at the subcollection {userId}/{title}/{subTitle}. But you haven't stated whether the document {userId}/{title} has been created yet.

Your query is fetching all documents in the collection {userId}. If you haven't created the document {userId}/{title} then you will not get back any documents.

Firestore paths (collections / documents / subcollections / documents / ...) is not a directory structure. Creating a/b/c/d does not mean that a/b will be created as well (though once you create a/b, if you had already created a/b/c/d then they will be associated).

Greg Fenton
  • 1,233
  • 9
  • 15
  • I can see in the console that they are getting created. I also updated the question. Not sure if it has to do with the fetching of the subcollection being asynchronous, but I can't figure it out. – Kevvv May 20 '21 at 21:32
  • Are you using [FlutterFire](https://firebase.flutter.dev/docs/overview) ? – Greg Fenton May 21 '21 at 01:01
  • No. Does it work with Swift? I'm just baffled that i'm having difficulty with such rudimentary querying from Firestore. All I literally want to do is get all the documents within a collection. I shouldn't have to use another library on top of Firebase. – Kevvv May 21 '21 at 01:55
  • Sorry, my bad. Did a search and came across some Flutter threads...and forgot that you are on Swift. – Greg Fenton May 21 '21 at 17:39
  • Based on the screenshot above of the Firebase Console, it seems that the datatype of the document ID is different than a string? If manually create a new docs with an ID of "foobar", does it "look different" in the list (compare the look of the `0x6cac0720c85374` with the `result.hash`). Could it be that you've created docs w/ IDs that are hex values, not strings (as your query is trying to fetch)? What happens if you change your above query code by removing the double-quotes? `self?.db.collection(user!.uid).document(0x6cac0720c8537467d7d2dccd9b88b8c757e10dfd3dcb8991ff71a4f8dfe1dd)` – Greg Fenton May 21 '21 at 17:45