Good afternoon.
I have 2 collections in mongoDB with a one-to-many relationship, where one of the collections receives the foreign key of the other.
const Sport = mongoose.model('Sport', new Schema({
_id: {
type: String,
default:() => uuid()
},
name: { type: String, required: true }
}))
const Event = mongoose.model('Event', new Schema({
_id: {
type: String,
default:() => uuid()
},
name: { type: String, required: true },
sport_id: { type: String, required: true }
}))
I want to do searches on these collections with graphql and when searching for Event, show the data from 'sport_id' instead of just showing the String. How do I do? How do I make the rootvalue?
type Sport {
_id: String
name: String
}
type Event {
_id: String
name: String
sport_id: Sport
}
type Query {
sport(name: String): [Sport!]
sportById(_id: String): Sport
event(name: String, sport_id: String): Event!
eventById(_id: String): Event
}
Related
I have an update call as below in my NestJs project to update a mongoose model.
async updateRole(role_id: ObjectId, request: any): Promise<any> {
return this.roleModel.findByIdAndUpdate(role_id, {...request});
}
Here is the request I'm passing
{
"name":"Super-Admin",
"application": "62b2dbfd82045f40ea884334",
"active":true,
"privileges": ["62b2dbfd82045f40ea884334","62b2dbfd82045f40ea884334"],
"updated_by": "Abhilash.Shajan1#gmail.com"
}
Below is my role schema
import * as mongoose from 'mongoose';
const Schema = mongoose.Schema;
const RoleSchema = new Schema({
name: {
type: String,
required: true
},
application: {
type: Schema.Types.ObjectId,
ref: 'Application',
autopopulate: true,
required: true
},
active: {
type: Boolean,
required: true
},
privileges: [{
type: Schema.Types.ObjectId,
ref: 'Privilege',
autopopulate: true
}],
created_by: {
type: String
},
created_at: {
type: Date
},
updated_by: {
type: String
},
updated_at: {
type: Date
}
});
RoleSchema.index( { name: 1, application: 1 }, { unique: true } );
export { RoleSchema };
I already created a document (This is the only document now present in the roles collection) with the above request. Now I'm trying to update its active field to true.
Since i have unique compound index in the schema, it does not allow me to update the active field, I'm getting unique contraint error on both application and name field.
This error will be meaningful if i have another document with same name and application in the collection, but there is not.
Another way is to pass the active field alone in the request. But it will not help in my case because the UI is always passing the whole fields which include the unchanged values as well.
Any suggestions ?
So this is an example of my schema I have for a user.
id: String,
email: String,
slug: {
type: Object,
phrase: {type: String, default: null},
},
When I want to define a new user and save that user, I would do the following;
const newUser = new User({
id: 123,
username: "CoolUser",
email: "BillGates#google.com"
});
newUser.save();
But this does not save the "slug" object, It was my understanding, that since I a default value for it, it would auto populate with that default value. What can I do to make it auto generate without having to define the whole schema again when saving a user?
You should add default for slug property, and not for his sub-property. Try changing your schema like this:
slug: {
type: {
phrase: { type: String },
},
default: {
phrase: null
},
},
try this:
const subschema = new Schema({
phrase: {type: String, default: null},
}, { _id: false });
and in your original schema:
id: String,
email: String,
slug: {
type: subschema,
default: () => ({})
},
this should do the trick.
const User = new Schema({
id: String,
about: {
bio: String,
location: String,
website: String,
discord: String,
twitter: String,
default: {
bio: "This is a default bio.",
location: "",
website: "",
discord: "",
twitter: "",
}
}
})
Ok here is the example, I removed some stuff from it just for ease, Basically as you can see I want bio to default to: This is a default bio.
But instead, I get the following error:
throw new TypeError(`Invalid schema configuration: \`${name}\` is not ` +
^
TypeError: Invalid schema configuration: `This is a default bio.` is not a valid type at path `about.default.bio`. See bit ly / mongoose-schematypes for a list of valid schema types.
I'm trying to filter my pets by category, I have the following model of pets:
const Pet = mongoose.model(
'Pet',
new Schema({
name: {
type: String,
required: true,
},
age: {
type: Number,
required: true,
},
description: {
type: String,
},
weight: {
type: Number,
required: true,
},
color: {
type: String,
required: true,
},
images: {
type: Array,
required: true,
},
available: {
type: Boolean,
},
category: Object,
user: Object,
adopter: Object,
}, { timestamps: true }),
);
module.exports = Pet;
when I try to get the data through postman it returns an empty array as a response.
my code to filter by category:
static async getByCategory(req, res) {
const id = req.params.id;
// check if id is valid
if (!ObjectId.isValid(id)) {
res.status(422).json({ msg: 'Invalid ID' });
return;
}
const pets = await Pet.find({ 'category._id': id }).sort('-createdAt');
if (!pets) {
res.status(404).json({ msg: 'Pets not found!' });
return;
}
res.status(200).json({ pets });
}
it's my first time using mongodb so i'm not sure what's wrong.
id being passed from the client side is string and the one which is saved in the db is ObjectId. Convert the string to Mongoose ObjectId before Pet.find().
const id = mongoose.Types.ObjectId(req.params.id);
const pets = await Pet.find({ 'category._id': id }).sort('-createdAt');
Don't forget to import 'mongoose'.
Could you check that your MongoDB indeed has a field category._id?
I'm sorry if this might be a duplicate question but I'm quite having a hard time understanding Mongoose. I am working on a Node.js project that implements Mongoose and MongoDB. What I want to accomplish is to modify and save some users' data through a call from a specific endpoint.
Mongoose Schema looks like this
var UserSchema = new Schema({
isAdmin: {type: Boolean, default: false},
name: String,
surname: String,
nickname: { type: String },
email: { type: String, lowercase: true, required: true, trim: true, unique: true, dropDubs: true },
password: { type: String, required: true },
salt: { type: String },
verified: { type: Boolean, default: false },
bio: {
type: { type: String, enum: [0,1] }, // 0='Appassionato', 1='Giocatore'
birthday: String,
height: Number,
number: Number,
role: { type: String, enum: [0,1,2,3] }, // 0='Playmaker', 1='Ala', 2='Guardia', 3='Centro'
team: String,
city: String,
aboutMe: String,
},
newsletter: {type: Boolean, default: false},
lastCheckin: {type: mongoose.Schema.Types.ObjectId, ref: 'Checkin'},
follows: [{type: mongoose.Schema.Types.ObjectId, ref: 'Structure'}],
score: { type: Number, default: 0 },
profilePicture: String,
lastLogin: {type: Date},
facebook: {
id: String,
accessToken: String,
profileImage : String
}
}, {
collection: 'users',
retainKeyOrder: true,
timestamps: true,
}).plugin(mongoosePaginate);
Following is the code for when the endpoint gets interrogated
exports.updateUser = (req,res) => {
var userId = req.params.userId;
var updates = req.body;
User.findOneAndUpdate({_id: userId}, {$set: updates}, (err, saved) => {
if (!err) {
console.log("Ritorno questo: " + saved);
return res.status(202).json(saved);
} else {
return res.status(500).json(saved);
}
});
};
As far as I understood, the method findOneAndUpdate exposed by Mongoose should find the document I'm looking for and then modify it and save it. This doesn't happen though.
Through PostMan I'm sending this JSON
{"bio.aboutMe":"Hello this is just a brief description about me"}
But PostMan is responding with the non-modified object. What am I missing here?
What you need to do is to add {new:true}, it give you back the updated document.
In the documentation :
If we do need the document returned in our application there is
another, often better, option:
> Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, { new: true },
> function (err, tank) { if (err) return handleError(err);
> res.send(tank); });
This is something I don't really like as there is another option if we don't want to have the document → update
So what you need to do is :
User.findOneAndUpdate({_id: userId}, {$set: updates}, {new:true}.....
hello i am new on mongodb and node js i have a question
here is my product schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const categorySchema = require('./category');
const ProductSchema = new Schema({
country: {
type: String,
required: [true, "country can't be null"]
},
city: {
type: String,
default: ""
},
name: {
type: String,
required: [true, "name can't be null"]
},
measureValue: {
type: Number,
default: 0
},
minPrice: {
type:Number,
required: [true, "minPrice can't be null"],
min: [1,"minPrice must be at least 1"]
},
maxPrice: {
type:Number,
required: [true, "maxPrice can't be null"],
min: [1,"maxPrice must be at least 1"]
},
photoUrl: {
type:String,
default: ""
},
explanation: {
type: String,
default: ""
},
category: [categorySchema.schema],
userID: {
type: String,
required: [true,"userid cant be null"]
},
isActive: {
type: Boolean,
default: true
},
createdDate: {
type: Date,
default: Date.now
},
deletedDate: {
type:Date
}
})
and here is my category schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CategorySchema = new Schema({
name: {
type: String,
required: [true, "name can't be null"]
},
createdDate: {
type: Date,
default: Date.now
},
deletedDate: {
type:Date
}
})
i need to do this;
every product data must be have category
if one day,one category's name changed then every product that relation with that category must changed
i am trying to set category id to product schema and when i fetch the data it must be comes every product with category name as json
i am really confused if you help me i'd be really thankful
You can set up your category as :
category: {
type: mongoose.Schema.Types.ObjectId,
ref: 'category' //your model name
}
You can wrap it into an array and name it categories if you want multiple categories.
Then when you get the data, you will have to execute new Product().populate('category') to get retrieve the category data instead of just returning the category ObjectId.