How can we achieve Joins in MongoDB? - mongodb

I have two collections in db,
1. products (product_id, name, status, price, unit_price)
2. cart_details (cart_id, product_id, quantity)
Problem I am facing is, I want to show descriptive record on cart details page from these both collections. Where unit_price and product_name will come from products collection while quantity will be used from cart_details collection. I referred Mongo DB's own documentation it do returns me collection with nested objects but problem with that is if i want to update quantity in cart_details collection it throw an exception of "type mismatch".
Don't know if there is any other way to join tables and on update of one collection it won't throw any error.
here is the update cart code.
exports.update = function(req, res) {
var cart = req.cart;
cart = _.extend(cart, req.body);
cart.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(cart);
}
});
};
and here is the cart service:
angular.module('core').factory('Cart', ['$resource',
function($resource) {
return $resource('cart/:cartId', { cartId: '#_id'
}, {
update: {
method: 'PUT'
}
});
}
]);

Related

mongoose.populate() with graphql is not able to perform 'infinite' queries

I have a stack of ApolloServer for GraphQL with MongoDB as a database with mongoose as a library.
I have now set up my code that I am able to perform some queries that goes 2-3 levels in to deep. But when I try to query further and go to my original object. It will return me with a null.
I have tried the solution of Academind already with some youtube films + searching the world of internet, however. No solutions found to this yet.
My resolver functions
module.exports = {
Query: {
athlete: async (root, args, context) => {
return await Athlete.findOne({ _id: args._id }).populate('results');
},
race: async (root, args) => {
return await Race.findOne({ _id: args._id }).populate('athletes');
},
result: async (root, args) => {
return await Result.findOne({ _id: args._id })
.populate('race')
.populate('athlete')
.exec();
},
athletes: async () => {
return await Athlete.find().populate('results');
},
races: async () => {
return await Race.find().populate('athletes');
},
results: async () => {
return await Result.find()
.populate('race')
.populate('athlete')
.exec();
}
}
};
Easier is to go to github though: https://github.com/axelvuylsteke/fullstack-graphql-vue/tree/graphQL_stackOverflow_question
npm run dev to start it in dev mode.
You can run the queries, first one you will get a null for the race.name, second one when you take results as a source root, you get a value for the name:
query searchAthlete {
athlete(_id: "5d690a25a1917025486c27ac") {
_id
country
results{
_id
race{
_id
name
}
}
}
}
query searchResults {
results {
_id
race{
_id
name
}
}
}
I expect to have infinite possibilities to go through the queries from object to object...
You can normally connect to the mongoDB as the dev mode is set to all open IP adresses.
Little background:
An athlete will store a race result.
A race will store all participated athletes.
A result will store the result itself with an athlete and the race where the result is performed.

Issue with getting information from mongodb

Ok so here is what I am trying to do, I have a Item collection that holds a users items along with price quantity and description. I have also created a collection called soldItems that will store information about a sold item once the user inputs the required data and submits the form. I am not sure if I am doing this correctly to begin with and I have been trying to research this but I don't exactly know what I am looking for.
Here is the code I have so far
router.post("/item/:id", middleware.isLoggedIn, (req, res) => {
Item.findById(req.params.id, (err, item) => {
if(err) {
console.log(err);
}
var soldItem = {
id: req.params.id,
item: req.item.name,
askPrice: req.item.price
};
var soldPrice = req.body.soldPrice;
var soldQuantity = req.body.soldQuantity;
var itemSold = {
soldItem: soldItem,
soldPrice: soldPrice,
soldQuantity: soldQuantity
};
SoldItem.create(itemSold, (err, newlyCreated) => {
if (err) {
console.log(err);
} else {
item.soldItems.push(newlyCreated);
item.save();
req.flash("success", "Item Sold");
res.redirect("back");
}
});
});
});
So... Item.findById(req.params.id) works because I am pulling the ObjectId from the url. However, how would I be able to use req.item._id. Because the issue I am having is when I am trying to get req.item.name and req.item.price I am being told that it cannot read property 'name' or 'price' of undefined. How can I get that information?

Mongo Set One Table Column as One Table's Option

Expecting a solution for this scenario. I have two tables. table 1 'team' contains'team_name' and table 2 'players' contains 'players_name' and 'players_team'. So, Here I want to insert data into players table. If I am inserting players_team in players table it should be a valid team name which exists on team table. How can I achieve this?
Note: This can be achieved by simply checking for the value in column first, But That is not what am looking for. I know in MySQL there is a method where the value of one's can be linked someway. I want to know whether the same can be achieved with mongo and mongoose
Your answer
router.post('/add_player', (req, res) => {
let teamid = req.body.teamid;
Teams.findOne({ _id: teamid }, (err, Team) => {
if (err) {
console.log(err)
} else {
if (Team == null) {
console.log("Team not found")
} else if (Team != null) {
console.log("Team Found")
//Add Player
let Data = {
players_team: teamid,
team_name: Team.team_name,//Valid team name
player_name: req.body.player_name,
}
Players(Data).save((err, SaveResult) => {
if (err) {
console.log(err);
} else {
console.log('player saved successfully')
res.status(200).send('player added successfully')
}
})
}
}
})
})

Save records into the same collection in Mongo DB using Meteor js

Being new to Meteor JS, I'm confused on how to update a record. I have 2 templates AddSchoolLayout and Schoolcontactlayout, AddSchoollayout creates the record in Mongo db, now, for the same school I want to add its address still on the same DB NewSchoolDB but as I tried this I keep getting the error below about wrong ID. What wrong am I to right?
Note that my language might not correlate with Mongo's; I'm still fresh, coming from the SQL background.
This is the method.js where the record is been saved.
//methods.js
if (Meteor.isServer) {
Meteor.methods({
SchoolRegister: function (phone, schoolemail) {
if (!Meteor.userId()) {
throw new Meteor.error('Not authorized');
return false;
}else{
NewSchoolDB.insert({
authorId: Meteor.userId(),
phone: phone,
schoolemail
});
}
}
});
}
This is the event for saving a new school
//add school
Template.AddSchoolLayout.events({
'submit .addnewschool': function (event, template) {
event.preventDefault();
var newschoolname = trimInput(event.target.newschoolname.value);
if (isNotEmpty(newschoolname)) {
Meteor.call('SchoolRegister', newschoolname,
function (error, response) {
if (error) {
Bert.alert(error.reason, 'danger', 'growl-top-right');
return false;
}else{
Bert.alert("School successfully created", "success", "growl-top-right");
FlowRouter.redirect('/schoolcontact');
}
});
}
return false;
}
});
This is where I want to update the school address
//school contact
Template.SchoolContactLayout.events({
'submit .contactschool': function (event) {
event.preventDefault();
var phone = trimInput(event.target.phone.value);
if (isNotEmpty(phone)) {
Meteor.call('SchoolRegister', phone, function (error, response) {
if (error) {
Bert.alert(error.reason, 'danger', 'growl-top-right');
return false;
}else{
Bert.alert('School address updated successfully', 'success', 'growl-top-right');
FlowRouter.redirect('/logo-upload');
}
});
}
return false;
}
});
Error logged on the console
I20170524-17:44:14.051(1)? at packages/ddp-server/livedata_server.js:559:43
I20170524-17:51:54.678(1)? Exception from sub NewSchoolDB id onFTu2j3xRmbqC5WF TypeError: this.userId is not a function
I20170524-17:51:54.710(1)? at [object Object]._handler (lib/pulbish/published.js:3:13)
I20170524-17:51:54.712(1)? at maybeAuditArgumentChecks (packages/ddp-server/livedata_server.js:1737:12)
I20170524-17:51:54.713(1)? at [object Object]._.extend._runHandler (packages/ddp-server/livedata_server.js:1035:17)
I20170524-17:51:54.714(1)? at [object Object]._.extend._startSubscription (packages/ddp-server/livedata_server.js:853:9)
I20170524-17:51:54.715(1)? at [object Object]._.extend.protocol_handlers.sub (packages/ddp-server/livedata_server.js:625:12)
I20170524-17:51:54.719(1)? at packages/ddp-server/livedata_server.js:559:43
Your SchoolRegister method accepts 2 arguments: phone and schoolmail. When you create the school you call the methods with one argument called newschoolname. So something is wrong here with your naming convention, but it shouldn't really matter regarding your question.
With MongoDB, you use insert to add a new record to your collection. If you need to update it, use update. So one way to solve your problem is to:
In AddSchoolLayout, call your method to insert the document the first time. NewSchoolDB.insert(...) will return the ID of the created record. Keep that ID and pass it to your next page, for exemple in the URL.
In your next page, SchoolContactLayout, you need to call a new method which is going to update your school, using the ID returned by the previous method. This new method will look something like this:
SchoolUpdate: function (schoolId, phone) {
if (!Meteor.userId()) {
throw new Meteor.error('Not authorized');
return false;
}else{
NewSchoolDB.update(schoolId, { $set: { phone } });
}
}
The first argument of the update MongoDB function is the ID of the record you want to update. The second arguments are the modifiers you want to use to update your record. Here is the full list of modifier you can use: update modifiers
EDIT: how to pass ID from one layout to another:
I didn't use FlowRouter for a while and I can't test it right now so you may have to do some correction, but here is how I would do it to give you an idea:
First you need to define your route SchoolContactLayout with something like this:
FlowRouter.route('/schoolcontact/:schoolId', {
name: 'schoolContact',
});
This adds a schoolId parameter to the route.
In your SchoolRegister method, get the return ID and return it:
var id = NewSchoolDB.insert({
authorId: Meteor.userId(),
schooleName
});
return { id }
Edit your redirection FlowRouter.redirect('/schoolcontact'); with FlowRouter.go('/schoolcontact/' + response.id);
You can then edit your contactSchool event with something like this:
Template.SchoolContactLayout.events({
'submit .contactschool': function (event) {
event.preventDefault();
var schoolId = FlowRouter.getParam('schoolId');
var phone = trimInput(event.target.phone.value);
if (isNotEmpty(phone)) {
Meteor.call('SchoolUpdate', schoolId ,phone, function (error, response) {
if (error) {
Bert.alert(error.reason, 'danger', 'growl-top-right');
return false;
}else{
Bert.alert('School address updated successfully', 'success',
'growl-top-right');
FlowRouter.redirect('/logo-upload');
}
});
}
return false;
}
});
Notice the var schoolId = FlowRouter.getParam('schoolId'); to get the ID from URL parameter so I can use it in the update method.

Sails.js Waterline native MongoDB query by ID?

I am trying to use the Waterline .native() method to query an item by id in the database. This is what my code looks like:
// Consutruct the query based on type
var query = {};
if (req.param('type') === 'id') {
query = { _id: req.param('number') };
} else {
query = { 'data.confirmationNumber': req.param('number') };
}
Confirmations.native(function(error, collection) {
if (error) {
ResponseService.send(res, 'error', 500, 'Database error.');
} else {
collection.find(query).toArray(function(queryError, queryRecord) {
if (queryError) {
ResponseService.send(res, 'error', 500, 'Database error.');
} else {
if (queryRecord.length > 0) {
ResponseService.send(res, 'success', 200, queryRecord[0]);
} else {
ResponseService.send(res, 'error', 404, 'Your confirmation details could not be found.');
}
}
});
}
});
When the query is 'data.confirmationNumber' it works but if it is '_id' it dows not work. How do I fix this?
if your Id is a ObjectId see this
var ObjectId = require('mongodb').ObjectID;
{_id: new ObjectId(req.param('number') )}
Iniside Model and in attribute define the id field like this
id : {type : 'objectid',primaryKey:true}
When you are querying the code
Here my model name is - QuizModel and the id is coming in the params quizId so here quizId is equal to the _id in the mongodb database
QuizModel.find({_id: QuizModel.mongo.objectId(quizId)})
.then(function(response){
})
.catch(function(error){
});