i'm trying to save a group with references to users and ranks. users and ranks is arrays of id's. However when i make a post request it seem to say that Group validation failed. What am i doing wrong with my references?
router.post('/:users/:game/:ranks/:age/:quantity/:usercount', function(req, res, next) {
var params = req.params;
var ranks = params.ranks.split(',');
var users = params.users.split(',');
var group = new Group({
users: users,
game: params.game,
ranks: ranks,
quantity: params.quantity,
age_above: params.age,
userCount: params.usercount
});
group.save(function(err, object) {
if (err) {
res.send(err);
} else {
User.findByIdAndUpdate(params.id, {$set:{group:object.id}}, {new: true}, function(err, doc){
if(err){
res.send(err);
} else {
res.send(doc);
}
}).populate('group');
}
});
});
User schema
var userSchema = new Schema({
_id: {
type: SchemaTypes.Long,
required: true,
unique: true,
index: {unique: true}
},
name: String,
birthday: Date,
country: String,
image: String,
group: { type: Schema.Types.ObjectId, ref: 'Group'},
games: [{
game: { type: Schema.Types.ObjectId, ref: 'Game'},
rank: { type: Schema.Types.ObjectId, ref: 'Ladder'},
userName: String
}],
friends: [{ type: Schema.Types.ObjectId, ref: 'User' }],
created_at: Date,
updated_at: Date
});
Error message
{
"message": "Group validation failed",
"name": "ValidationError",
"errors": {
"users": {
"message": "Cast to Array failed for value \"[ '10210697939629739' ]\" at path \"users\"",
"name": "CastError",
"kind": "Array",
"value": [
"10210697939629739"
],
"path": "users",
"reason": {
"message": "Cast to ObjectId failed for value \"10210697939629739\" at path \"users\"",
"name": "CastError",
"kind": "ObjectId",
"value": "10210697939629739",
"path": "users"
}
}
}
}
Related
little bit stuck with mongoose. I want to get all users projects where he's added. Tried few options, but in all of them I receive an empty array. So the main question is it possible somehow to find all project by filtering/finding the Project model?
This is how looks my default response to understand what I'm looking for:
{
"_id": "61a8bc4e8e24f10ac7a7288d",
"name": "Random project",
"description": "Random project desc",
"maxWorkingEmployees": 5,
"status": "Paused",
"createdBy": {
"_id": "61a66578f2dabf7555bcf4ab",
"email": "Henrikas#furniture1.eu",
"role": "Owner"
},
"currentlyWorkingEmployees": [
{
"username": "Ema",
"role": "Employee",
"_id": "61a8e0423140ecce769dc971"
}
],
"createdAt": "2021-12-02T12:30:06.461Z",
"updatedAt": "2021-12-02T15:11:51.361Z",
"__v": 0
}
Project model:
const mongoose = require('mongoose');
const SingleUserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
role: {
type: String,
required: true,
},
});
const ProjectSchema = new mongoose.Schema(
{
name: {
type: String,
required: [true, 'Provide project name'],
minlength: 5,
},
description: {
type: String,
required: [true, 'Provide description about the project'],
},
maxWorkingEmployees: {
type: Number,
required: [
true,
'Provide maximum number of employees working on this project',
],
},
currentlyWorkingEmployees: [SingleUserSchema],
status: {
type: String,
enum: ['Pending', 'In progress', 'Paused', 'Delayed', 'Completed'],
default: 'Pending',
},
createdBy: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: true,
},
},
{ timestamps: true }
);
module.exports = mongoose.model('Project', ProjectSchema);
Here's my controller and my first try:
const getMyProjects = async (req, res) => {
const userId = req.user.userId;
const projects = await Project.find({
currentlyWorkingEmployees: { _id: userId },
});
res.json({projects});
};
Second shot after reading some articles
const getMyProjects = async (req, res) => {
const userId = req.user.userId;
const projects = await Project.aggregate([
{
$match: {
currentlyWorkingEmployees: { _id: userId },
},
},
]);
};
As I said in the comment you can do it accessing to the internal object of the schema with an string accessing to it child object.
Project.find({'currentlyWorkingEmployees._id': userId})
I am trying to create an API in node to get nearby users with the same pet_type.
UPDATE: After Reading the first answer and as per the documentation. I update my user model and I Tried using populate but it doesn't get me all the pets data of the user.
User Model
var UserSchema = new mongoose.Schema({
password: String,
first_name: String,
email: String,
location: {
type: { type: String },
coordinates: []
},
pets: {
type: mongoose.Schema.ObjectId,
ref:'Pet', default:null
}
});
Pet Model
var PetSchema = new mongoose.Schema({
name: String,
pet_type: String,
breed: String,
owner_id: {type: mongoose.Schema.ObjectId, ref:'User', default:null},
});
Current Query
var lat = req.query.lat;
var lng = req.query.lng;
User.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [lng, lat]
},
$maxDistance: 10000
}
},
_id:{ $nin :req.decoded._id }}, function(err, users) {
if(err) {
res.json({success:false, message:"No listing found", error:err});
return;
} else {
res.json({success:true, message:"User found", data:users});
return;
}
}).populate('pets');
output
{
"success": true,
"message": "Pet data",
"data": [
{
"location": {
"type": "Point",
"coordinates": [
72.53808,
23.02622
]
},
"pets": null,
"_id": "5f32cb544f6b1a07acd75f48",
"phone": "1234567890",
"email": "qwewqe#qwe.com",
"first_name": "qwertt",
}
]
}
You can use the .populate() method
Solution :
You can use lookup (aggregation) in mongodb
link : https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/
link : https://www.isummation.com/blog/perform-inner-join-in-mongodb-using-lookup-aggregation-operator/
I want different values from the nested schema. How can I populate them so that every field is showing me its nested data and not the object ID?
I'm using MongoDB and node/express.
This is my postDB where the post schema is defined:
const mongoose = require('mongoose');
var postSchema = new mongoose.Schema({
title: {
type:String,
required:true
},
body: {
type:String,
required:true
},
comments:[{
type: mongoose.Schema.Types.ObjectId,
ref: "comment"
}],
category:{
type:String,
required:true
},
creator: {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
}
},{timestamps : true}
)
module.exports = mongoose.model('postData', postSchema);
This is my commentDB which is referenced from the postDB:
const mongoose = require('mongoose');
// Using the Schema constructor, create a new CommentSchema object
// This is similar to a Sequelize model
var CommentSchema = new mongoose.Schema({
// `body` is of type String
creator: {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
},
body: String
},{timestamps : true});
var Comment = mongoose.model("comment", CommentSchema);
module.exports = Comment;
This is how I'm trying to populate:
router.get('/READ', (req,res)=>{
posts.find({}, function (err, post) {
if (err) {
console.log(err);
}else{
res.json({post})
}
}
)
.populate([{path:'creator'}, {path:'comments'}])
})
However the results i get from this does not populate every object ID.
For example:
{
"comments": [
{
"_id": "5f8d91d8f8550044f0f755c8",
"creator": "5f84e5b1d893ac42dcc9cb78",
"body": "This looks cool",
"createdAt": "2020-10-19T13:17:12.323Z",
"updatedAt": "2020-10-19T13:17:12.323Z",
"__v": 0
},
{
"_id": "5f8d92e82ecfbe34b8f6375b",
"creater": "5f84e5b1d893ac42dcc9cb78",
"body": "hello",
"createdAt": "2020-10-19T13:21:44.463Z",
"updatedAt": "2020-10-19T13:21:44.463Z",
"__v": 0
},
],
"_id": "5f887cef6fd7d34548a592ea",
"title": "A DESCRIPTIVE PARAGRAPH EXAMPLE",
"body": "\"The room in which I found myself was very large and lofty. The windows were ",
"category": "Finance",
"creator": {
"joined": "2020-10-15T12:14:23.888Z",
"posts": [
"5f887cef6fd7d34548a592ea",
"5f887e0d6fd7d34548a592ec",
"5f887e266fd7d34548a592ed",
"5f887e586fd7d34548a592ee",
"5f89bfccc2bebd40b07b044a",
"5f89c36e906bbb27b84af897",
"5f89c7614199d52b141ff249",
"5f89c7ea4199d52b141ff24a",
"5f8c5ab175ef762ed89eddba",
"5f8c5be2d7fac046f0021d9f"
],
"_id": "5f88481d00ed460960da90f8",
"username": "kenwaysharma",
"email": "kenwaysharma#gmail.com",
"password": "$2b$10$p3qjmdSKWIF9qAagZoqbjuG34cjOgXTe5XYER0aowwviIS65COVlu",
"__v": 0
},
"__v": 0,
"updatedAt": "2020-10-20T05:42:56.320Z"
}
Here is the userDB:
username: {
type: String,
required: [true, "Username is required!"],
unique: true,
lowercase: true,
},
email:{
type: String,
required: [true, "Email is required!"],
unique: true,
lowercase: true,
validate: [isEmail, "Please enter a valid email!"]
},
password:{
type: String,
required: [true, "Password is required!"],
minlength: [6, "Enter atleast 6 characters!"],
},
comments:[{
type: mongoose.Schema.Types.ObjectId,
ref: "comment"
}],
posts:[{
type: mongoose.Schema.Types.ObjectId,
ref: "postData"
}],
},{timestamps : true});
GET users:
router.get('/USERS', (req,res)=>{
User.find({}, function (err, user) {
if (err) {
console.log(err);
}else{
res.send(user)
}
}
).populate('comments') .populate('posts')
})
How do I get the creator data inside of comments instead of just its object ID?
Update:
I also tried selecting the creator inside comments like
.populate('comments', 'creator')
but it still gives me the creator object ID in a string.
Update 2:
I have added the code for userDB to which the commentDB and postDB references.
Also added the GET users just to see how it works in postman.
Try chaining multiple populate methods and using the exec method to pass your callback.
posts.find({})
.populate({
path: 'comments',
populate: {
path: 'creator',
model: 'user'
}
})
.populate('creator')
.exec(function (err, post) {
if (err) {
console.log(err);
}else{
res.json({post})
}
});
I have tried other similar kind of questions available but nothing seems to work for me.
I have two collections:
leads:
const mongoose = require("mongoose");
const id = mongoose.Schema.Types.ObjectId;
const leadsSchema = mongoose.Schema(
{
_id: id,
userId: { type: id, ref: "User", required: true },
leadName: String,
leads: [
{
_id: id,
name: String,
status: { type: String, required: false, default: "New" },
leadActivity: { type: String, required: false, default: "No Campaign Set" },
headline: { type: String, required: false },
location: { type: String, required: false },
leadType: { type: id, ref: "LeadsCategory", required: true },
}
],
campaignAssociated: {type: id, ref: "campaign"},
},
{
timestamps: true
}
);
module.exports = mongoose.model("lead", leadsSchema);
leadCategory
const mongoose = require("mongoose");
const leadsCategorySchema = mongoose.Schema(
{
_id: mongoose.Schema.Types.ObjectId,
name: {
type: String,
required: false,
},
leadsData: [{ type: Array, ref: "lead" }],
},
{ timestamps: true }
);
module.exports = mongoose.model("LeadsCategory", leadsCategorySchema);
I am trying to reference/populate the name of the lead from leadscategory schema into the leads
exports.get_single_lead_info = (req, res) => {
const { userId } = req.user;
const { leadid } = req.body;
let idToSearch = mongoose.Types.ObjectId(leadid);
Lead.aggregate([
{
$lookup: {from: 'leadscategories', localField: 'leadType', foreignField: 'name', as: 'type as'}
},
{
$match: {
userId: mongoose.Types.ObjectId(userId),
},
},
{
$unwind: "$leads",
},
{
$match: {
"leads._id": idToSearch,
},
},
])
.exec(function (err, result) {
if (err) {
return res.status(400).json({ message: "Unable to fetch data", err });
}
if (!result.length) {
res.status(404).json("No result found");
} else {
res.status(200).json({ message: "Lead info found", result });
}
});
};
But it outputs me the lookup result as an empty array everytime:
{
"message": "Lead info found",
"result": [
{
"_id": "5ece11cbac50c434dc4b7f2c",
"leadName": "python",
"leads": {
"status": "New",
"leadActivity": "Campaign Set",
"name": "Hailey",
"headline": "Machine Learning | Python",
"location": "New Delhi Area, India",
"_id": "5ece11cbac50c434dc4b7f29",
"leadType": "5ebce0f81947df2fd4eb1060"
},
"userId": "5eba83d37d4f5533581a7d58",
"createdAt": "2020-05-27T07:07:55.231Z",
"updatedAt": "2020-05-27T10:47:42.098Z",
"__v": 0,
"type as": [] //<--- Need lead type name associated inside this
}
]
}
Input: "leadid": "5ece11cbac50c434dc4b7f29"
Any help appreciated.
[
{
$match: {
userId: mongoose.Types.ObjectId(userId),
},
},
{
$unwind: "$leads",
},
{
$match: {
'leads._id': idToSearch,
},
},
{
$lookup: {
from: 'leadscategories',
localField: 'leads.leadType',
foreignField: '_id',
as: 'type as'
}
},
]
I have this "User" model where I store friends, this friends have some option
// Prepare schema
var schema = new db.Schema({
friends: [{
active : Boolean,
user : { type: db.Schema.ObjectId, ref: 'user' },
options : [{ type: db.Schema.ObjectId, ref: 'friend_option' }],
}],
image: { type: db.Schema.ObjectId, ref: 'file' },
password: {
type: String,
select: false
},
email: String,
name: String,
udid: [{
device: String,
udid: String
}],
created_on: Date
});
here I get one user with his friends
var friendQuery = User.find( {_id:req.params.id});
friendQuery.select('friends');
friendQuery.populate({ path: 'friends._id', model: 'user', select:'_id name' });
friendQuery.exec(
function(err, user) {
if (err)
res.send(err);
res.send(user);
});
my question is, why the result have a different name from my model? why friends->_id->_id instead go friends->user->_id?
friends": [
{
"_id": {
"_id": "58025664c154929d3207b232",
"name": "User 1"
},
"options": [
],
"active": false
},
{
"_id": {
"_id": "580257e1e3cd4fc7326fa97b",
"name": "User 2"
},
"options": [
],
"active": false
}
]
another option, this solution is good for an hypothetical big app?
The way You are using this in incorrect just make a simple change in your query
var friendQuery = User.find( {_id:req.params.id});
friendQuery.select('friends');
friendQuery.populate({ path: 'friends.user', model: 'user', select:'_id name' });
friendQuery.exec(
function(err, user) {
if (err)
res.send(err);
res.send(user);
});
as you are taking reference of your user in friends array simply replace _id from query to user that will definitely work for you