假设我们有一个名为'todos'的根集合。
此集合中的每个文档都包含:
title
:String todo_items
子集todo_items
中的每个文档都有
title
:String completed
:Boolean 我知道默认情况下在Cloud Firestore中查询很浅,这很好,但是有没有办法查询todos
并自动获得包含子集合todo_items
的结果?
换句话说,如何进行以下查询包括todo_items
子集?
db.collection('todos').onSnapshot((snapshot) => {
snapshot.docChanges.forEach((change) => {
// ...
});
});
答案 0 :(得分:36)
不支持此类查询,但我们将来可能会考虑这种情况。
答案 1 :(得分:3)
如果有人仍然有兴趣知道如何在firestore中进行深度查询,那么这是我提出的云函数getAllTodos的一个版本,它返回所有具有'todo_items'子集合的'todos'。
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;
})
}
答案 2 :(得分:0)
我遇到了同样的问题,但是对于IOS,如果我得到你的问题,如果你使用auto-ID作为待办事项收集文件的任何方式,如果你将文件ID存放在标题字段的下方,那将很容易 就我而言:
let ref = self.db.collection("collectionName").document()
let data = ["docID": ref.documentID,"title" :"some title"]
因此,当您检索时,我们会说出一系列待办事项,当您点击任何项目时,您可以通过路径轻松导航
ref = db.collection("docID/\(todo_items)")
我希望我能给你确切的代码,但我不熟悉Javascript
答案 3 :(得分:0)
我使用了AngularFirestore(afs)和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))
);
}
答案 4 :(得分:0)
如其他答案所指出,您不能请求深度查询。
我的建议:尽可能少地复制数据。
我也遇到了“宠物所有权”的同样问题。在搜索结果中,我需要显示用户拥有的每只宠物,但是我还需要能够自己搜索宠物。我最终重复了数据。我将在每个用户以及pets子集合上拥有pets数组属性。我认为这是我们在这种情况下能做的最好的事情。
答案 5 :(得分:0)
根据文档,您需要对 firestore 进行两次调用。一次获取 doc
,第二次获取 subcollection
。
减少总时间的最佳方法是使用 promise.All
或 promise.allSettled
并行执行这两个调用,而不是顺序调用。
答案 6 :(得分:-1)
你可以尝试这样的事情
db.collection('coll').doc('doc').collection('subcoll').doc('subdoc')
希望这有帮助!