I want to query and response for API. I have 2 collections "Account" and "User". "User" has "id" field and "Account" has "user_id" field - both of us is one. One "User" has one or many Account and it has "id" field in "Account" collection. I want to query "id" from "User" collection and expect the result detail of this User and 1 field "accounts_id" into it.
This is all my expected result to look like:
https://sample-accounts-api.herokuapp.com/
I tried to collect "accounts_id" but I can not know how to query and add it to "User" detail.
This is my collect "accounts_id":
exports.findAllAccountIDforUser = (req, res) => {
Account
.find({user_id: req.param('user_id')})
.then(result => {
let a = result.map(data => {
return data.id;
})
res.send({'accounts_id':a});
})
}
My "User" Schema:
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
const Account = require('../model/account');
var UserSchema = new mongoose.Schema({
id: {type: Number, unique: true},
name: String,
});
const User = mongoose.model('User', UserSchema);
module.exports = User;
My "Account" Schema:
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var AccountSchema = new mongoose.Schema({
id: {type: Number},
user_id: {type: Number, ref: 'User'},
name: String,
balance: Number
});
const Account = mongoose.model('Account', AccountSchema);
module.exports = Account;
using async-await you can do it in 4 lines.
get user
get all accounts related to that user
assign user.account_ids=accounts
send response.
exports.findAllAccountIDforUser = async(req, res) => {
let user=await User.findOne({id:req.param('user_id')});
let accounts= await Account.find({user_id: req.param('user_id')}).select(' _id id);
user.account_ids=accounts;
res.send(user);
}
another way is using promises like you are already doing it.
exports.findAllAccountIDforUser = (req, res) => {
User
.findOne({id:req.param('user_id')})
.then(user=>{
Account
.find({user_id: req.param('user_id')})
.then(result => {
let a = result.map(data => {
return data.id;
})
user.account_ids=a;
res.send(user);
})
})
}
I have answer for thís:
exports.findAlldetail = (req, res) => {
User
.aggregate([
{
$match: {
id: +req.param('id')}
},
{
$lookup: {
from: "accounts",
localField: "id",
foreignField: "user_id",
as: "account_ids"
}
},
{
$project: {
_id: 0,
id: 1,
name: 1,
"account_ids.id": 1
}
}
])
.then(result => {
result.account_ids = result.map(data => {
data.account_ids = data.account_ids.map(b => b.id);
})
res.send({"attributes":result});
})
}
Related
I would like to ask on how I can save a Sub Category by getting the ID of the Category.
Category Model
import mongoose from 'mongoose'
const categorySchema = mongoose.Schema({
name: {
type: String,
required: true,
},
})
const Category = mongoose.model('Category', categorySchema)
export default Category
Sub Category model
import mongoose from 'mongoose'
const subCategorySchema = mongoose.Schema({
subname: {
type: String,
required: true,
},
categoryid: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Category',
},
})
const SubCategory = mongoose.model('SubCategory', subCategorySchema)
export default SubCategory
My Controller
const createSubCategory = asyncHandler(async (req, res) => {
const { subname, categoryid} = req.body
const subCategoryExists = await SubCategory.findOne({
subcategoryname,
}).populate('categoryname')
if (subCategoryExists) {
res.status(400)
throw new Error('SubCategory already exists')
}
const name = await Category.find({}).populate('_id')
const subCategory = new SubCategory({
categoryid: name,
subcategoryname,
})
const createdSubCategory = await subCategory.save()
if (createdSubCategory) {
res.status(201).json({
_id: createdSubCategory._id,
categoryid: createdSubCategory,
subname: createdSubCategory.subname,
})
} else {
res.status(400)
throw new Error('Invalid SubCategory')
}
})
My question is
How am I going to save my Sub Category in which I will select the ID Value of the Category and insert it to the Sub Category - categoryname field ? Is is working but all I gets is the first ID in the category even if you typed another ID.
I wanted to have something like this upon saving in mongodb
SubCategory
{
_id: 123,
subcategory: "Sub Category",
categoryname:{
_id: 123456(categoryid),
categoryname: "Categoryname"
}
}
I have managed to figure it out, you need to make it match. In your request.body you have your field name called categoryid so in the Category.FindOne({_id:}
you need to match what you type in categoryid to the findone of _id in order for you to get that. :D
const createSubCategory = asyncHandler(async (req, res) => {
const { subname, categoryid} = req.body
const subCategoryExists = await SubCategory.findOne({
subcategoryname,
}).populate('categoryname')
if (subCategoryExists) {
res.status(400)
throw new Error('SubCategory already exists')
}
const id= await Category.find({_id: categoryid}).populate('_id')
const subCategory = new SubCategory({
categoryid: id,
subcategoryname,
})
const createdSubCategory = await subCategory.save()
if (createdSubCategory) {
res.status(201).json({
_id: createdSubCategory._id,
categoryid: createdSubCategory,
subname: createdSubCategory.subname,
})
} else {
res.status(400)
throw new Error('Invalid SubCategory')
}
})
I am trying to add an item to a MongoDB array with RESTAPI through Axios. I thought it would look similar to the push method but I have no idea how to do that.
my Model is of a person:
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: String,
password: String,
friends: [],
missions: []
})
const personModel = mongoose.model('Person', PersonSchema);
I want to add a mission to the mission array of a person.
and for example, in order to add a new Person, I use NodeJS and API:
(api.js)
router.post('/api/people', (req, res) => {
const personToAdd = req.body;
const newPersonPost = new personModel(personToAdd);
newPersonPost.save((e) => {
if (e) {
console.log("error");
}
});
res.json({
msg: 'Received'
})
});
and in the client side I use Axios:
axios({
url: 'http://localhost:8080/api/people',
method: 'POST',
data: dataToUpdate
})
.then(() => {
console.log('axios sent info to server');
}).catch((e) => {
console.log('error' + e);
})
Thank you so much!
express
router.post('updating mission endpoint url', async (req, res) =>
try {
const query = { /* content */}; /* write a query to retrieve the concerned user by using a unique identifier */
let person = await personModel.findOne(query);
person.missions.push(req.body.mission);
personModel.save();
} catch (err) {
console.log(err);
}
});
client
In the client side you just have to put the mission you want to add in data like you did above with the right endpoint url and you should add a unique identifier for the user you want to add mission to.
[] will not assign array type to your variable.
Change your schema file with the following:
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: { type: String },
password: { type: String },
friends: { type: Array },
missions: { type: Array }
})
Update the db model entity file with following
First method:
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: String,
password: String,
friends: {type : Array},
missions: {type : Array}
})
const personModel = mongoose.model('Person', PersonSchema);
Second Method :
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: String,
password: String,
friends: [{ type: String }],
missions: [{ type: String }]
})
const personModel = mongoose.model('Person', PersonSchema);
You can update the array object as per your requirements.
You just want to be using the $push update operator, very simple, like so:
db.collection.updateOne(
{
_id: user._id
},
{
"$push": {
"missions": {
mission: newMission
}
}
})
Mongo Playground
Its been a tough time for me trying to figure this out.
The problem I'm trying to solve is this:
I have USERS who has list of COMPANIES,
this COMPNAY has list of PROJECTS etc.
I'm trying to create a PROJECT under a COMPANY and a COMPANY under a USER using referencing.
This USER is going to be populated from form fields likewise COMPANY PROJECT
USERS SCHEMA
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//============= User Schema============//
const userSchema = new Schema({
name: String,
email: String,
//referencing user's company/companies
company: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'company',
},
],
},{
timestamps: true
});
const Users = mongoose.model('user', userSchema);
module.exports = Users;
COMPANY SCHEMA
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//======== Company schema ========//
const compSchema = new Schema({
company_name: String,
//referencing user schema
user: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'user',
},
],
//referencing projects
projects: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'project',
},
],
},{
timestamps: true
});
const Company = mongoose.model('company', compSchema);
module.exports = Company;
PROJECT SCHEMA
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//PROJECT SCHEMA
const projectSchema = new Schema({
project_title: String,
//referencing company schema
company: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'company',
}
],
},{
timestamps: true
});
const Projects = mongoose.model('project', projectSchema);
module.exports = Projects;
CONTROLLERS
const Users = require('./userSchema');
const Company = require('./companySchema');
const Projects = require('./projectSchema');
//create user
exports.createUser = async (req, res) => {
const data = {
name: req.body.name,
email: req.body.email,
}
Users.create(data, (err, done) => {
if(err) return err;
res.json({UserData: done});
return;
});
}
exports.getAllUsers = async(req, res) => {
}
//create company
exports.createCompany = async (req, res) => {
const CompanyData = {
company_name: req.body.company_name,
}
Company.create(companyData, (err, done) => {
if(err) return err;
res.json({CompanyDetails: done});
return;
});
}
exports.getllCompany = async (req, res) => {
}
//create project
exports.createProject = async (req, res) => {
const projectData = {
project_title: req.body.project_title,
}
Projects.create(projectData, (err, done) => {
if(err) return err;
res.json({ProjectDetails: done});
return;
});
}
exports.getAllProjects = async (req, res) => {
}
I understand that populate can be used to push documents to children. Any assistance offered will be highly appreciated
Store reference
Firstly, while creating a Company inside createCompany controller, you should add user _id in users array like this:
const CompanyData = {
company_name: req.body.company_name,
users: [req.body.userId] // Lets assume, user _id is coming in request body
}
Company.create(companyData, (err, done) => {
// Your code
});
Then, when you create a Project, add _id of Company you just created, in createProject controller like this:
const projectData = {
project_title: req.body.project_title,
company: [req.body.comapnyId] // Again assuming, company _id is coming in request body
}
Projects.create(projectData, (err, done) => {
// Your code
});
Update reference
Also, as I see in your schemas, you are trying to keep it bidirectional, like user's _ids in company doc & company's _ids in user doc.
To achieve this, if you create a user, you should update the corresponding company with pushing(addToSet actually) new user _id in user array.
Example:
To create a user in controller, run two scripts synchronously one-by-one:
Create a user with company _id and other details.
const data = {
name: req.body.name,
email: req.body.email,
company: [req.body.companyId]
}
Users.create(data, (err, done) => {
// Your code
});
Update company doc(whose _id is saved in above user) with _id of newly created user.
const updateCompany = { "$addToSet": { user: user._id } }; // Get `user._id` from above synchronous script
Company.update({_id: req.body.companyId}, data, (err, done) => { // Updated filter
// Your code
});
This is my table schema
var mongoose=require("mongoose");
var tableSchema=new mongoose.Schema({
tName:String,
keys:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"key"
}
],
fields:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"field"
}
]
})
module.exports=mongoose.model("table",tableSchema);
----Key Schema
var mongoose=require("mongoose")
var keySchema=new mongoose.Schema({
name:[String],
value:[String]
})
module.exports=mongoose.model("key",keySchema);
---field Schema
var mongoose=require("mongoose")
var fieldSchema=new mongoose.Schema({
name:[String],
value:[String]
})
module.exports=mongoose.model("field",fieldSchema);
----How I Pushed into
app.post("/table/:id/value",function(req,res){
var Key={
name:req.body.key,
value:req.body.keyValue
}
var Field={
name:req.body.field,
value:req.body.fieldValue
}
table.findById(req.params.id,function(err,foundTable){
if(err){
console.log(err)
}
else{
console.log(foundTable)
key.create(Key,function(err,createKey){
foundTable.keys.push(createKey)
console.log(createKey)
})
field.create(Field,function(err,createField){
foundTable.fields.push(createField)
console.log(createField)
})
foundTable.save();
console.log(foundTable);
res.redirect("/table/"+req.params.id)
}
})
})
ObjectId are not being refernced
Here is the Image that prints the table
How I populated the table
app.get("/table/:id",function(req,res){
table.findById(req.params.id).populate("keys").populate("fields").exec(function(err,foundTable){
if(err){
console.log(err)
res.redirect("/")
}
else{
console.log(foundTable);
res.render("show",{table:foundTable})
}
})
})
I Dont know where I had gone wrong,
everything seems to be fine but
the objected is not referenced when printed and
it is not being populated
How it should be printed reference: https://bezkoder.com/mongoose-one-to-one-relationship-example/
This is an example:
1st schema
const mongoose = require("mongoose");
const Customer = mongoose.model(
"Customer",
new mongoose.Schema({
name: String,
age: Number,
gender: String
})
);
module.exports = Customer;
2nd schema
const mongoose = require("mongoose");
const Identifier = mongoose.model(
"Identifier",
new mongoose.Schema({
cardCode: String,
customer: {
type: mongoose.Schema.Types.ObjectId,
ref: "Customer"
}
})
);
module.exports = Identifier;
How it should be printed
{
_id : ObjectId("5da000be062dc522eccaedeb"),
cardCode : "5DA000BC06",
customer : ObjectId("5da000bc062dc522eccaedea"),
__v : 0
}
How it should be populated
[ { _id: 5da135bf61a1dd3e9c2a6e82,
cardCode: '5DA135BD61',
customer:
{ _id: 5da135bd61a1dd3e9c2a6e81,
name: 'bezkoder',
age: 29,
gender: 'male',
__v: 0 },
__v: 0 } ]
try this .populate([ 'keys', 'fields' ])
The reason why keys and fields are not inserted is that the foundTable.save() will be executed before creating the new Key and Field documents and push there _id to the foundTable.
One way to solve the issue is by using async/await. You can modify your code as below using async/await
app.post("/table/:id/value", async function (req, res) {
var Key = {
name: req.body.key,
value: req.body.keyValue,
};
var Field = {
name: req.body.field,
value: req.body.fieldValue,
};
try {
const foundTable = table.findById(req.params.id);
const createKey = await key.create(Key);
const createField = await field.create(Field);
foundTable.keys.push(createKey._id);
foundTable.fields.push(createField._id);
await await foundTable.save();
res.redirect("/table/"+req.params.id)
} catch (err) {
console.log(err);
// handle failure here
}
});
This will make sure the Key and Field are created and _id is pushed to foundTable before saving the foundTable
Regarding the populate query. Looks like once you save the _id of Field and Key in foundTable your existing query itself should work
I'm trying to implement notifications into my app but I'm having trouble figuring out how to store the id's of the sender and receiver into my notification schema below.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const notificationSchema = mongoose.Schema({
sender: [{
type: Schema.Types.ObjectId,
ref: 'user'
}],
receiver: [{
type: Schema.Types.ObjectId,
ref: 'user'
}],
seen: {
type: Boolean
},
notificationMessage: {
type: String
},
created: {
type: Date
}
})
const Notifications = mongoose.model('notification', notificationSchema);
module.exports = Notifications;
I have a controller trying to create a new notification below
const User = require('../models/User');
const Notification = require('../models/Notification');
module.exports = {
getNotifications: async (req, res, next) => {
const { _id } = req.params;
const user = await User.findById(_id).populate('notification');
console.log('user', user)
res.status(200).json(user.notifications);
},
createNotification: async (req, res, next) => {
const { _id } = req.params;
const newNotification = new Notification(req.body);
console.log('newNotification', newNotification);
const user = await User.findById(_id);
newNotification.user = user;
await newNotification.save();
let sender = new User({id: user._id});
newNotification.sender.push(sender);
let receiver = new User({id: user._id});
newNotification.receiver.push(receiver);
await user.save();
res.status(201).json(newNotification);
}
}
The problem is once I try to create a notification, nothing is stored, the notification schema returns with this.
newNotification { sender: [], receiver: [], _id: 5bd1465d08e3ed282458553b }
I'm not entirely sure how I can go about storing the user id's into their respective references in the notification schema, any idea on what I can do to fix this?
EDIT: changed createNotification
Just change the variable name when push user data in notification
let sender = new User({id: user._id, name: user.name}):
newNotification.sender.push(sender); //for store sender
let reciever = new User({id: user._id, name: user.name}):
newNotification.receiver.push(reciever); //for store reciever
You are trying to store ObjectId in the array but adding the whole user object and mongoose schema doesn't allow fields which are not defined in the schema so change newNotification.sender.push(user._id) in the createNotification function.