Самая эффективная схема, которую я могу придумать, следующая:
Firestore-root
|
--- questions (collections)
| |
| --- questionId (document)
| |
| --- questionId: "02cubnmO1wqyz6yKg571"
| |
| --- title: "Question Title"
| |
| --- date: August 27, 2018 at 6:16:58 PM UTC+3
| |
| --- comments (colletion)
| | |
| | --- commentId
| | |
| | ---commentId: "5aoCfqt2w8N8jtQ53R8f"
| | |
| | ---comment: "My Comment"
| | |
| | ---date: August 27, 2018 at 6:18:28 PM UTC+3
| |
| --- likes (colletion)
| | |
| | --- likeId (document)
| | |
| | --- userId: true
| |
| --- views (colletion)
| | |
| | --- viewId (document)
| | |
| | --- userId: true
| |
| --- tags ["tagId", "tagId"]
|
--- tags (collections)
|
--- tagId (document)
|
--- tagId: "yR8iLzdBdylFkSzg1k4K"
|
--- tagName: "Tag Name"
, в котором comments
, likes
и views
являются коллекциями в документе questionId
. В отличие от базы данных реального времени Firebase, где для отображения списка вопросов вы бы скачали весь объект вопроса, в Cloud Firestore это больше не проблема. Поэтому, чтобы избежать запросов с использованием where
методов, вы можете просто получить конкретный вопрос, подобный этому:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
DocumentReference questionIdRef = rootRef.collection("questions").document(questionId);
questionIdRef.get().addOnCompleteListener(/* ... */);
Поскольку вы можете иметь сотни, тысячи или даже больше комментариев, лайков и просмотров к одному вопросу, сохранение данных в массиве вам не поможет. Согласно официальной документации :
Cloud Firestore оптимизирован для хранения больших коллекций небольших документов.
Например, чтобы получить все комментарии к конкретному вопросу, вы можете использовать следующий запрос:
Query query = rootRef.collection("questions/"+questionId+"comments").orderBy("date", Query.Direction.DESCENDING);
Поскольку вопрос может иметь только несколько тегов, вы можете просто использовать массив. Чтобы получить все вопросы с определенным тегом, вы можете использовать следующий запрос:
Query query = rootRef.collection("questions/"+questionId+"tags").whereArrayContains("tags", tagId);
Еще одна вещь, которую следует запомнить, даже если tags
объект хранится в базе данных в виде массива, document.get("tags")
вернет ArrayList
, а не array
.
Если вы также хотите посчитать количество лайков или любое другое количество документов в коллекции, см. Мой ответ из этой записи .
Edit:
По вашим комментариям:
Если я хочу показать пользователю наиболее понравившийся вопрос. Как я мог это сделать?
Вы должны добавить количество лайков в качестве свойства внутри объекта вопроса, а затем вы можете запросить базу данных в соответствии с этим следующим образом:
Query query = rootRef.collection("questions").orderBy("numberOfLikes", Query.Direction.DESCENDING);
В соответствии с этим вы также можете хранить количество лайков в базе данных реального времени Firebase и увеличивать / уменьшать его, используя Firebase транзакции .
во-вторых, если я хочу показать все вопросы, связанные с тегом вроде математики (показать все вопросы, для которых есть тег математики) ??
Как уже упоминалось выше, вы можете воспользоваться преимуществом whereArrayContains
метода. Вы также можете хранить теги как String, а не как id. Для этого вам нужно изменить эту структуру:
--- tags ["tagId", "tagId"]
до
--- tags ["mathematics", "chemistry"]
И код должен выглядеть так:
Query query = rootRef.collection("questions/"+questionId+"tags").whereArrayContains("tags", "mathematics");
оператор (userId: true) сохраняет много повторений данных
Да, это так.