One to one relationships in mongodb with mongoose - node.js

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.

Related

Update a value in another collection for multiple documents when one value is changed in one document in another collection MongoDb

I am making a group chat type of functionality where my database (Mongodb) have two collections
Groups
Users
Now the Groups collection have the data of all the groups that exists in my app and each document conatains information about an individual group and have information about the users who are in this group.
On the other hand the user have the information of all the groups he/she is joined in.
Now the problem is i have implemented the "Leave Group" functionality as it was pretty simple i just had to remove the data of that group from that particular user's information, but i dont know how to implement the "Delete Group" functionality.
Because if i delete the information about the group from group's collection by changing the active field to false , then still the users have that information and when they log in they will see that group listed because its not deleted from there document ,this is the code according to what i explained:-
app.post('/delete_group' , function(req,res){
const group_id = req.body.group_id
var delete_group= { $set: {active:false}}
group.updateOne({_id:server_id} , delete_group, function(err,data){
if(err) console.log(err)
else{
if(data.modifiedCount>0){
console.log('deleted the group')
res.json({status:200})
}
}
})
})
Now if i use the brute force approach of using either updateMany or updateOne with for loop i have to update the information in each user's document, and that feels a little ineffecient way , so is there any way to do this more efficiently? Like some refrence system or anything else , I can't think of anything else.

How to load mongoose Schema from the collection name

Ideally, for populate to work during queries in mongoose, both the schemas of that which is been populated and the calling schema needs to be imported in same file under same repo.
Now, I have a scenario where a schema called AuthorSchema was created by another internal micro-service in another repo which is pointing to the same database as my own service and I wish to populate it during my queries.
Is there a way to automatically decode the AuthorSchema from the author collection name after I've connected to the database?
E.g
let posts = await Post.find({})
.populate("author", 'first_name last_name _id').limit(10)
Where I have created postSchema in my own service but authorSchema was created by another micro-service in another repo called author-management-microservice and as such I have no access to that schema.
What I would want is something like:
let AuthorSchema = mongoose.connection.decodeSchemaFromCollectionName('author');
Such that I can modify my query to something like
let posts = await Post.find({})
.populate({path:"author", model:AuthorSchema, select:'first_name last_name _id'}).limit(10)
The reason I want something like this is because I have been battling with MissingSchemaError: Schema hasn't been registered for model "Author". whenever I try to populate author and I don't want to copy around duplicate schema files across different micro-services.
To get the schema from a registered Mongoose model, you need to access the schema specifically:
const AuthorSchema = require('mongoose').model('Author').schema;
Is there a way to automatically decode the AuthorSchema from the author collection name after I've connected to the database?
No - the schema is saved at the code level, not the database level. There is no way to know the schema just from connecting to the database.

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.

Sub documents vs Mongoose population

I have the following senario:
A user can login to a website. A user can add/delete the poll(a question with two options). Any user can give there opinion on the poll by selecting anyone of the options.
Considering the above scenario I have three models - Users Polls Options . They are as follows, in order of dependency:
Option Schema
var optionSchema = new Schema({
optionName : {
type : String,
required : true,
},
optionCount : {
type : Number,
default : 0
}
});
Poll Schema
var pollSchema = new Schema({
question : {
type : String,
required : true
},
options : [optionSchema]
});
User Schema: parent schema
var usersSchema = new Schema({
username : {
type : String,
required : true
},
email : {
type : String,
required : true,
unique : true
},
password : String,
polls : [pollSchema]
});
How do I implement the above relation between those documents. What exaclty is mongoose population? How is it different from subdocuments ? Should I go for subdocuments or should I use Mongoose population.
As MongoDb hasn't got joins as relational databases, so population is a something like hidden join. It just means that when you have that User model and you will populate Poll Model, mongoose will do something like this:
fetch User
fetch related Polls, by ObjectIds which are stored in User document
put fetched Polls documents into User document
And when you will set User as document and Polls as subdocument, it will just mean that you will put whole data in single document. At one side it means that to fetch User Polls, mongoose doesn't need to run two queries(it need to fetch only User document, because Polls data is already there).
But what is better to choose? It just depends of the case.
If your Polls document will refer in another documents (you need access to Polls from documents User, A, B, C - it could be better to populate it, but not for sure. The advantage of populating is fact, that when you will need to change some Polls fields, you don't need to change that data in every document which is referring to that Polls document(as it will be a subdocument) - in that case in document User, A, B, C - you will only update Polls document. As you see it's nice. I told that it's not sure if populating will be better in that case, because I don't know how you need to retrieve your Polls data. If you store you data in wrong way, you will get performance issues or have some problems in easy data fetch.
Subdocuments are the basic way of storing data. It's great when Polls will be only referring to User. There is performance advantage - mongoose need to do one query instead of two as in population and there is no previously reminded update disadvantage, because you store Polls data only in single place, so there is no need to update other documents.
Basically MongoDb was created to mostly use Subdocuments. As the matter of fact, it's just non-relational database. So in most cases I prefer to use subdocuments. I can't answer which way will be better in your case, because I'm not sure how your DB looks like(in a full way) and how you want to retrieve your data.
There is some useful info in official documentation:
http://mongoosejs.com/docs/subdocs.html
http://mongoosejs.com/docs/populate.html
Take a look on that.
Edit
As I prefer to fetch data easily, take care about performance and know that data redundancy in MongoDb is something common, I will choose to store this data as subdocuments.

Mongoose access multiple collection

In mongodb I have one collection named as People.
It contains:
_id:Number,
name:String,
friends:[{friendsId:{type:Schema.Types.ObjectId,ref:'People'},addedTime: Date}]
I want to search a name of friend of a particular user and return the _id of that friend in a single query using mongoose in node.js.
Its impossible to retrieve the data in a single query/populate. Since mongodb is not a relational database. Iterate the data separately & give the result as callback to next query.

Resources