Cloud Firestore deep get with subcollection

后端 未结 6 1158
离开以前
离开以前 2020-12-07 18:34

Let\'s say we have a root collection named \'todos\'.

Every document in this collection has:

  1. title: String
  2. subcollection named
相关标签:
6条回答
  • 2020-12-07 18:55

    As pointed out in other answers, you cannot request deep queries.

    My recommendation: Duplicate your data as minimally as possible.

    I'm running into this same problem with "pet ownership". In my search results, I need to display each pet a user owns, but I also need to be able to search for pets on their own. I ended up duplicated the data. I'm going to have a pets array property on each user AS WELL AS a pets subcollection. I think that's the best we can do with these kinds of scenarios.

    0 讨论(0)
  • 2020-12-07 19:02

    you could try something like this

    db.collection('coll').doc('doc').collection('subcoll').doc('subdoc') 
    

    Hope this helps !

    0 讨论(0)
  • 2020-12-07 19:04

    I used AngularFirestore (afs) and Typescript:

    import { map, flatMap } from 'rxjs/operators';
    import { combineLatest } from 'rxjs';
    
    interface DocWithId {
      id: string;
    }
    
    convertSnapshots<T>(snaps) {
      return <T[]>snaps.map(snap => {
        return {
          id: snap.payload.doc.id,
          ...snap.payload.doc.data()
        };
      });
    }
    
    getDocumentsWithSubcollection<T extends DocWithId>(
        collection: string,
        subCollection: string
      ) {
        return this.afs
          .collection(collection)
          .snapshotChanges()
          .pipe(
            map(this.convertSnapshots),
            map((documents: T[]) =>
              documents.map(document => {
                return this.afs
                 .collection(`${collection}/${document.id}/${subCollection}`)
                  .snapshotChanges()
                  .pipe(
                    map(this.convertSnapshots),
                    map(subdocuments =>
                      Object.assign(document, { [subCollection]: subdocuments })
                    )
                  );
              })
            ),
            flatMap(combined => combineLatest(combined))
          );
      }
      

    0 讨论(0)
  • 2020-12-07 19:07

    This type of query isn't supported, although it is something we may consider in the future.

    0 讨论(0)
  • 2020-12-07 19:07

    I have faced the same issue but with IOS, any way if i get your question and if you use auto-ID for to-do collection document its will be easy if your store the document ID as afield with the title field in my case :

    let ref = self.db.collection("collectionName").document()
    
    let data  = ["docID": ref.documentID,"title" :"some title"]
    

    So when you retrieve lets say an array of to-do's and when click on any item you can navigate so easy by the path

    ref = db.collection("docID/\(todo_items)")
    

    I wish i could give you the exact code but i'm not familiar with Javascript

    0 讨论(0)
  • 2020-12-07 19:10

    If anyone is still interested in knowing how to do deep query in firestore, here's a version of cloud function getAllTodos that I've come up with, that returns all the 'todos' which has 'todo_items' subcollection.

    exports.getAllTodos = function (req, res) {
        getTodos().
            then((todos) => {
                console.log("All Todos " + todos) // All Todos with its todo_items sub collection.
                return res.json(todos);
            })
            .catch((err) => {
                console.log('Error getting documents', err);
                return res.status(500).json({ message: "Error getting the all Todos" + err });
            });
    }
    
    function getTodos(){
        var todosRef = db.collection('todos');
    
        return todosRef.get()
            .then((snapshot) => {
                let todos = [];
                return Promise.all(
                    snapshot.docs.map(doc => {  
                            let todo = {};                
                            todo.id = doc.id;
                            todo.todo = doc.data(); // will have 'todo.title'
                            var todoItemsPromise = getTodoItemsById(todo.id);
                            return todoItemsPromise.then((todoItems) => {                    
                                    todo.todo_items = todoItems;
                                    todos.push(todo);         
                                    return todos;                  
                                }) 
                    })
                )
                .then(todos => {
                    return todos.length > 0 ? todos[todos.length - 1] : [];
                })
    
            })
    }
    
    
    function getTodoItemsById(id){
        var todoItemsRef = db.collection('todos').doc(id).collection('todo_items');
        let todo_items = [];
        return todoItemsRef.get()
            .then(snapshot => {
                snapshot.forEach(item => {
                    let todo_item = {};
                    todo_item.id = item.id;
                    todo_item.todo_item = item.data(); // will have 'todo_item.title' and 'todo_item.completed'             
                    todo_items.push(todo_item);
                })
                return todo_items;
            })
    }
    
    0 讨论(0)
提交回复
热议问题