Ответ 1
Этот тип запроса не поддерживается, хотя это то, что мы можем рассмотреть в будущем.
Скажем, у нас есть корневая коллекция с именем 'todos'.
В каждом документе этой коллекции есть:
title
: Строкаtodo_items
Каждый документ в субколлекции todo_items
имеет
title
: Строкаcompleted
: BooleanЯ знаю, что запрос в Cloud Firestore по умолчанию неглубокий, что здорово, но есть ли способ запросить todos
и получить результаты, которые включают подколлекцию todo_items
автоматически?
Другими словами, как сделать следующий запрос, включите подколлекцию todo_items
?
db.collection('todos').onSnapshot((snapshot) => {
snapshot.docChanges.forEach((change) => {
// ...
});
});
Этот тип запроса не поддерживается, хотя это то, что мы можем рассмотреть в будущем.
Если кому-то все еще интересно знать, как сделать глубокий запрос в firestore, вот версия облачной функции getAllTodos, которую я придумала, которая возвращает все 'todos', у которых есть подколлекция 'todo_items'.
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;
})
}
Я столкнулся с той же проблемой, но с IOS, каким-либо образом, если я получу ваш вопрос, и если вы используете автообъект для документооборота, то это будет легко, если в вашем хранилище будет ID документа как поле с полем заголовка в моем случае:
let ref = self.db.collection("collectionName").document()
let data = ["docID": ref.documentID,"title" :"some title"]
Итак, когда вы извлекаете, давайте скажем массив дел и при нажатии на любой элемент, который можно легко перемещаться по пути
ref = db.collection("docID/\(todo_items)")
Я хочу, чтобы я мог дать вам точный код, но я не знаком с Javascript
Я использовал 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))
);
}
Как указано в других ответах, вы не можете запрашивать глубокие запросы.
Моя рекомендация: дублируйте свои данные как можно меньше.
Я сталкиваюсь с той же самой проблемой с "владением животным". В моих результатах поиска мне нужно отобразить каждого питомца, которым владеет пользователь, но я также должен иметь возможность самостоятельно искать питомцев. В итоге я продублировал данные. Я собираюсь иметь свойство массива питомцев для каждого пользователя, КАК ХОРОШО, как подколлекцию питомцев. Я думаю, что лучшее, что мы можем сделать с такими сценариями.
вы можете попробовать что-то вроде этого
db.collection('coll').doc('doc').collection('subcoll').doc('subdoc')
Надеюсь, это поможет!