Database modeling for firestore. Collection - categories - node.js

So i'm trying to model a database schema for firestore. It's called categories and i don't know how to store items. I tried watching https://fireship.io/lessons/advanced-firestore-nosql-data-structure-examples/. It looks logical, there are documents witch hold their children id and parent id, if parent is top level, then parent is null, but how to send data from back-end(Node.js) to front-end(Vue.js).
Is there any other approach?

You can read the data from Firestore using its service from the firebase package.
Let's say you have a collection (called a table in SQL databases) called Users and you want to access the document (called a row in SQL databases) with the id of 1. You can do this via this snippet:
import firebase from 'firebase/app'
import 'firebase/firestore'
const firestore = firebase.firestore()
const data = firestore.collection('Users').doc('1').get()
.then(snapshot => {
console.log(snapshot.data())
})

The important thing to note when working with Firestore is that there are collections and documents. Collections, for example categories_name can store multiple documents, which are stored by {id}. For example,
.collection("categories")
.doc("all")
.collection("todos")
.doc("DataForTodo")
.set(data);
For more information on exactly how to structure Firestore, please refer to the official documentation: https://firebase.google.com/docs/firestore/manage-data/structure-data

Related

Firestore , Python: Updating multiple documents with different fields for each document

Is there a way to update multiple documents which belong to various Collections? I want to update firestore fields for multiple documents, these fields for each document have to be updated with different values.
I tried the following but it only updates for one document. Anyone please assist.
db = firestore.client()
batch = db.batch()
docs = db.collection('some collections').document('some document').collection('some collection').document('some document')
batch.update(docs, {u'some firestore field': value]})
batch.update(docs, {u'another firestore field': value']})
batch.commit() `

One to one relationships in mongodb with mongoose

I have 2 databases named Users and Links. Whenever a new user signup, one collection is created in Users with unique id. What I want is to create another collection in Links with a field userId that has id of the newly created user. Also I want the id of the new collection from Links to be added in the newly created user collection. How can I achieve this with mongoose and mongodb?
What I understood was to write 3 queries as follows:
const user = await User.create({req.body}) //comes from the client side
const link = await Link.create({userId: user._id})
const updatedUser = await User.findOneAndUpdate({_id: user._id}, {link: link._id})
What I want to know, Is this the correct way?
It's not directly answering your question but you might want to reconsider your choice of database types. Since you're talking about querying by keys across multiple tables where records have some kind of relationship you might want to have a look at relationship databases like PostgreSQL for instance.

How can I select specific fields using the firestore modular api

In the <= V8 Firestore API I could query a set of documents and extract a subset of fields with code like the following:
const membersRef = db.collection('members');
const snapshot = await membersRef.select('First', 'Last').get();
With the new modular api I can do the following:
import { collection } from 'firebase/firestore';
const membersRef = collection(db,'members');
// how to select only First and Last from members ?
I can't find a select() function to specify fields in the new api. How can this be done using the V9 modular api?
I know I can read the entire collection and use .map()/.forEach to reduce the fields but I have some large fields I would rather not query unless I need them for a specific document. The use of select to have the server pull out only the fields needed is useful.
The client-side SDKs for Firebase don't have a select method/function, but always retrieve full documents. So the select method didn't exist in the v8 CollectionReference or Query classes, nor does it exist as a top-level function in the v9 modular SDK.
There is a select() method in the Admin SDK for Node.js, but that one still works as a method on CollectionRefence as far as I can tell.

How to fetch all documents from a firebase collection where each document has some sub collection and in sub collection there is a document?

I am making an Admin dashboard. I want to show all user's details and their orders. When I want to fetch all documents inside the user collection its returning empty. For more In user collection, each document has some sub-collection. In the account sub-collection, there is a document exists with name details where user account details are available as shown in snapshots.
My code is
export function getUsers() {
return firebase.firestore().collection("users").get();
}
If you store user's details directly in the document instead of 'account' sub-collection then fetching "users" collection will return all users' documents with their data. If you say there's no reason then I'd recommend doing this.
Other option would be to use collectionGroup query on "account" which will fetch all the documents from sub-collections named as "account" i.e. giving you every user's account details.
const snap = await db.collectionGroup('account').get()
const users = snap.docs.map(d => ({id: doc.ref.parent.parent.id, data: d.data()))
Here, id is user's document ID.
Firestore queries only access a single collection, or all collections with a specific name. There is no way to query a collection based on values in another collection.
The most common options are:
Query the parent collection first, then check the subcollection for each document. This approach works best if you have relatively few false positives in the parent collection.
Query all child collections with a collection group query, then check the parent document for each result. This approach works best if you have relatively few false positive in your child collection query.
Replicate the relevant information from the child documents into the parent document, and then query the parent collection based on that. For example, you could add a hasOrders field or an orderCount in the user document. This approach always gives optimal results while querying, but requires that you modify the code that writes the data to accommodate.
The third approach is typically the best for a scalable solution. If you come from a background in relation databases, this sort of data duplication may seen unnatural, but it is actually very common in NoSQL databases where you often have to change your data model to allow the queries your app needs.
To learn more about this, I recommend reading NoSQL data modeling and watching Getting to know Cloud Firestore.

Why is data retrieved from Firestore returning empty array when there are subcollections present?

I am trying to retrieve data from my the my firestore database using angularfire2.
This is what my current database looks like. I have a users collection that contains the userId doc which binds the userDetails and userPosts together.
However when I query this collection, it returns an empty array in the console.
I am using a firebase function to retrieve the data.
Firebase Function Index.ts
export const getFeed = functions.https.onCall(async (req,res) =>{
const docs = await admin.firestore().collection('users').get()
return docs.docs.map(doc => {
return {
postID: doc.id,
...doc.data()
}
})
})
TS File
tabTwoFeedInit (){
const getFeed = this.aff.httpsCallable('getFeed')
this.ajax = getFeed({}).subscribe(data=> {
console.log(data)
this.posts = data
})
}
How can I retrieve data from this firebase database successfully?
Firestore reads are shallow, and so they won't return subcollections automatically. Thus, your get() will only return the document ID, since the document has no fields.
To return the subcollections of a document, you need to call the getCollections method on that document. This can only by done by the admin API, but that should be fine for you since you are running inside a cloud function. As the documentation notes, it is generally expected that collection names are predictable (as they appear to be in your case), but if they aren't, you might consider restructuring your data.
Why are shallow reads desirable? It makes it possible to avoid retrieving potentially large collections of information that might be associated with, say, a user, so you can structure data more naturally. Depending on the size of the data, its possible that a field that is a map might make more sense for userDetails (but a collection is probably the right thing for userPosts).
If you are just creating the cloud function to retrieve the posts from this structure. I would prefer to restructure the database a bit and just use Collection Group Query on client side (with no requirement of cloud functions) to pull the posts.
By restructuring I mean, you should store userID inside the documents of userPosts sub collection.
Then simply user Collection Group Query to retrieve post of specific users.
The syntax is of firebase javascript library. You can find it's equivalent of angularfire
let posts= db.collectionGroup('userPosts').where('userId', '==', 'some-user-id');
I also ran into the same problem but I solved it by adding a field to the particular document i am trying to retrieve.Sometimes the cause is because the documents you are trying to get has no field in it. What I mean is that a document must have a field before the server can recognize it as an existing document.
Possibly there may be no field in the document you are trying to retrieve which makes tye server say it is not existing and so will not be retrieved.
So if you run into this problem, then consider adding a field to that document before you can successfully retrieve it.

Resources