retrieving array data in mongodb which match id - mongodb

Below is the schema. i want to get the answers as per matched qid, but i am getting all the answers in the answers array. i have tried almost all the queries but not able to understand why is this happening, if you could give link to other article that will be helpful too.
const id = req.params.id;
Channel.findOne({answer: {qid: {$in: [id]}}})
.then(result => {
console.log(result);
// let userAnswer;
// userAnswer = result.answer.map(i => {
// return {userId: i.userId , userName: i.userId.name, answer: i.answer}
// });
// res.json({ans: userAnswer, question: result.content});
})
.catch(err => {
console.log(err);
});
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const channelSchema = new Schema({
name: {
type: String,
required: true
},
category: {
type: String,
required: true
},
creator: {
type: String,
required: true
},
subscribers: [{type: mongoose.Types.ObjectId, required: true, ref: 'User'}],
content: {
question: [{
title: {type: String, required: true},
userId: {type: mongoose.Types.ObjectId, required: true, ref: 'User'}
}]
},
answer: [{
answer: {type: String, required: true},
qid: {type: mongoose.Types.ObjectId, required: true},
userId: {type: mongoose.Types.ObjectId, required: true, ref: 'User'}
}]
});
const model = mongoose.model('Channel', channelSchema);
module.exports = model;

const id = req.params.id;
return Channel.findOne({answer: {qid: {$in: [id]}}})
.then(snapshot => {
const results = [];
snapshot.forEach(doc => {
results.push({
id: doc.id,
data: doc.data()
});
});
return results;
})
})
.catch(err => {
console.log(err);
});
This is the way when you are going to fetch one array record. Not tested, only to show you how to get single record from collection

Related

Populate data using another collection in mongoose v6.2.8

Im having issues populating my mongoDB collection with another collection based off the _id. It Keeps returning an empty object with no errors or anything?
Property Schema
const PropertySchema = new Schema({
landlord: {
type: Schema.Types.ObjectId,
ref: "Landlord",
required: true,
},
...
});
Landlord Schema
import { Schema as _Schema, model } from "mongoose";
const Schema = _Schema;
const LandlordSchema = new Schema({
fname: {
type: String,
required: true,
},
lname: {
type: String,
required: true,
},
phone: {
type: Number,
required: true,
},
email: {
type: String,
required: true,
},
company: {
type: String,
},
});
const Landlord = (module.exports = model("Landlord", LandlordSchema));
export function get(callback, limit) {
Landlord.find(callback).limit(limit);
}
Property Controller
exports.readProperty = async (req, res) => {
await Property.find({ _id: req.params.propertyId })
.populate({
path: "Landlord",
select: "fname lname email phone company",
model: "Landlord",
strictPopulate: false,
})
.then(function (err, property) {
if (err) return res.send(err);
res.json(property);
});
};
mongodb Property Collection
Mongodb Landlord Collection
When running the get call from postman it returns:
I fixed this issue by selecting the field: landlord not Landlord

How to Populate CartItem schema product details into Order Schema using mongoose

I want to populate the details of products in my order. Currently it is only adding product id inside the products array. I tried a couple of methods but none seems to work.
import mongoose from 'mongoose'
const CartItemSchema = new mongoose.Schema({
product: {type: mongoose.Schema.ObjectId, ref: 'Product'},
quantity: Number,
shop: {type: mongoose.Schema.ObjectId, ref: 'Shop'},
status: {type: String,
default: 'Not processed',
enum: ['Not processed' , 'Processing', 'Shipped', 'Delivered', 'Cancelled']}
})
const CartItem = mongoose.model('CartItem', CartItemSchema)
const OrderSchema = new mongoose.Schema({
products: [CartItemSchema],
customer_name: {
type: String,
trim: true,
required: 'Name is required'
},
customer_email: {
type: String,
trim: true,
match: [/.+\#.+\..+/, 'Please fill a valid email address'],
required: 'Email is required'
},
delivery_address: {
street: {type: String, required: 'Street is required'},
city: {type: String, required: 'City is required'},
state: {type: String},
zipcode: {type: String, required: 'Zip Code is required'},
country: {type: String, required: 'Country is required'}
},
payment_id: {},
updated: Date,
created: {
type: Date,
default: Date.now
},
user: {type: mongoose.Schema.ObjectId, ref: 'User'}
})
const Order = mongoose.model('Order', OrderSchema)
export {Order, CartItem}
I tried doing this:
const create = async (req, res) => {
try {
req.body.order.user = req.profile;
console.log(req);
let order = new Order(req.body.order);
let neworder = await Order.findById(order._id)
.populate("products.product", "name price")
.populate("products.shop", "name")
.exec();
// console.log(order);
let result = await order.save();
sendMail(order);
res.status(200).json(result);
} catch (err) {
return res.status(400).json({
error: errorHandler.getErrorMessage(err),
});
}
};
Also tried using this for poulating the product details but doesnt seem to work!
Order.findById(order._id).populate({ path: "products.product", select: "_id name price" })

MongoDB: Find items with the user id

I have a product collection and a user collection where I reference user to my product collection.
So far what I am trying to achieve here is to get only the products that are created by that user.
const getOwnerProduct = expressAsyncHandler(async (req, res) => {
const activeUser = await User.findById(req.user._id)
const pageSize = 10
const page = Number(req.query.pageNumber) || 1
const items = { user: { _id: activeUser } }
const count = await Product.countDocuments({ ...items } )
const products = await Product.find({ ...items }).limit(pageSize).skip(pageSize * (page - 1))
res.json({ products, page, pages: Math.ceil(count / pageSize) })
})
Here's the Product Schema:
const productSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
name: {
type: String,
required: true
},
price: {
type: Number,
required: true,
},
description: {
type: String,
required: true
},
email: {
type: String
},
rating: {
type: Number,
required: true,
default: 0
},
image: {
type: String,
required: true,
default: 0
},
}, { timestamps: true
})
And here's the userSchema:
const userSchema = mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
phone: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
role: {
type: String,
enum: ['administrator', 'productOwner', 'regular'],
default: 'regular'
}
}, { timestamps: true
})
Here's the router:
app.use('/api/products', productRoutes)
router.route('/').get(getProducts, admin).get(getOwnerProducts, productOwner)
For some reason this doesn't work. I think my query on mongodb is not correct.
Any idea what am I missing here?
Here instead of const products = await Product.find({ ...items }) you can try
await User.findById(req.user._id).forEach(element =>{Product.find({user=element._id})});
or
await User.findById(req.user._id).forEach(element =>{Product.find(user=element._id)});

Mongoose populate method on query returns empty array

I am having trouble querying my model, and using the .populate method to grab referenced documents of my object. Here are my schemas:
var userSchema = new Schema({
firstname: { type: String, required: true, unique: false },
lastname: { type: String, required: true, unique: false },
...
children: [{type: mongoose.Schema.Types.ObjectId, ref: 'Child'}],
});
var childSchema = new Schema({
firstname: { type: String, required: true, unique: false },
lastname: { type: String, required: true, unique: false },
...
legal_guardian_id: [{type: mongoose.Schema.Types.ObjectId, ref: 'User'}],
});
And here is how i'm trying to run my query:
User.findOne({ _id: '5b9d30083e33585cc0b8c710' })
.populate('children').exec((err, doc) => {
if (err) { return console.error(err); }
res.send(doc);
})
This results in "children": []
When I just use the findOne method and return the user, I get "children":["5b9d3f23d1408c5f4e2624f3"].
What am I doing wrong?

Mongoose populate is not a function

I want the post's creator to be a user Schema. So i have 2 Schema
post.js
const mongoose=require('mongoose');
mongoose.Promise = global.Promise;
const Schema= mongoose.Schema;
const postSchema= new Schema({
body:{ type: String, required:true, validate:bodyValidators},
createdBy: { type: Schema.Types.ObjectId,ref:'User'}, // this one
to: {type:String, default:null },
createdAt: { type:Date, default:Date.now()},
likes: { type:Number,default:0},
likedBy: { type:Array},
dislikes: { type:Number, default:0},
dislikedBy: { type:Array},
comments: [
{
comment: { type: String, validate: commentValidators},
commentator: { type: String}
}
]
});
module.exports = mongoose.model('Post',postSchema);
user.js
const mongoose=require('mongoose');
mongoose.Promise = global.Promise;
const Schema= mongoose.Schema;
const userSchema=new Schema({
email: { type: String, required: true, unique: true, lowercase: true, validate: emailValidators},
username: { type: String, required: true, unique: true, lowercase: true, validate: usernameValidators},
password: { type: String, required: true,validate: passwordValidators},
bio: { type:String,default:null},
location: {type:String, default:null},
gender: {type:String,default:null},
birthday: { type:Date,default:null},
img: { type:String, default:'Bloggy/uploads/profile/avatar.jpeg'}
});
module.exports = mongoose.model('User',userSchema);
When a user creates a new post, I save his _id into a new post object
const post= new Post({
body: req.body.body,
createdBy:user._id,
createdAt:Date.now()
});
And when i want to recover all posts with their assigned author
router.get('/allPosts',(req,res)=>{
Post.find().populate('createdBy').exec((err,posts)=>{
if(err){
res.json({success:false,message:err});
}
else{
if (!posts) {
res.json({success:false,message:"No posts found"});
}
else{
res.json({success:true,posts:posts});
}
}
}).sort({'_id':-1}); // the latest comes first
});
It doesn't work though i've followed the documentation. The error i get is TypeError: Post.find(...).populate(...).exec(...).sort is not a function
What am I doing wrong ? Am I missing something ? Maybe the fact that both models are not in the same file ?
Remove execPopulate() it might work. It worked for me.
.exec() returns a Promise and has no method called .sort().
.sort() goes before .exec() as in Post.find(...).populate(...).sort(...).exec(...)
Look at 3rd example in the documentation.