I'm trying to create a small prediction game for football world cup with MEAN stack, but I have a problem that I need to get all the predicted games of user and all that are not predicted yet separately.
My schemas are (users schema is the default mean-stack):
/**
* Prediction Schema
*/
var PredictionSchema = new Schema({
game_id: {
type: Schema.ObjectId,
ref: 'Game'
},
user: {
type: Schema.ObjectId,
ref: 'User'
},
date: {
type: Date,
default: Date.now
},
choice: {
type: Number
}
});
And game schema:
var GameSchema = new Schema({
team1_key: {
type: String
},
team1_title: {
type: String
},
team2_key: {
type: String
},
team2_title: {
type: String
},
play_at: {
type: Date
},
score1: {
type: Number
},
score2: {
type: Number
}
});
mongoose.model('Game', GameSchema);
Anyway, what I'm trying to achieve is to get all games that are mentioned in all predictions and with the active user.
I tried like this, but it does not work:
/**
* List of Games predicted
*/
exports.allPredicted = function(req, res) {
Game.find({_id: {$in: Prediction.distinct('game_id')}}).sort('-created').populate('user', 'name username').exec(function(err, games) {
if (err) {
res.render('error', {
status: 500
});
} else {
res.jsonp(games);
}
});
};
What's wrong? I got error:
Error: Failed to lookup view "error" in views directory "/Users/username/Projects/ProjectName/server/views"
Any ideas? Thanks! :)
EDIT:
Got distinct values, not sure if this the create way of doing it, but anyway works.. almost:
exports.allPredicted = function(req, res) {
Prediction.distinct('game_id').populate('user', 'name username').exec(function(err, predictions) {
if (err) {
res.render('error', {
status: 500
});
} else {
console.log(predictions);
Game.find({_id: {$in: predictions }}).sort('-created').populate('user', 'name username').exec(function(err, games) {
if (err) {
res.render('error', {
status: 500
});
} else {
res.jsonp(games);
}
});
}
});
};
Now I need, that it should consider the active user as well. Any help?
you can find your active user in
req.user
so try
Prediction.find({user : req.user._id}).sort('-created').populate('game_id').exec(function(err, predictions) {
if (err) {
res.render('error', {
status: 500
});
} else {
res.jsonp(predictions);
}
});
This should return all the predictions made by your user and replace the game_id by the game associated.
ps: I don't test it but i think this is the logic of request you're looking for.
ps2 : see http://mongoosejs.com/docs/populate.html if you want to populate your users data too
Related
I have a collection of online users here goes its model
var SessionDetailSchema = mongoose.Schema({
providerID: {
type: String
},
firstName: {
type: String
},
email: {
type: String
},
status: {
type: String
}
},{ timestamps: true });
var sessionDetail = module.exports = mongoose.model('OnlineUser', SessionDetailSchema);
I am trying to send an array of providerID's so that I wanted to check the collection which all providerId's are present and return me those providerID details.
and this is what I tried
router.post('/sessiondetails:find', function (req, res, next) {
console.log(req.body.providerID)
sessionDetail.find({ "providerID": { $in: req.body.providerID} }, function (err, users) {
if (users) {
console.log(users)
} else {
console.log("not there")
}
})
})
unfortunately, I am getting the only first providerid response for multiple times.
i am sending the array from the postman it looks like this
{
"providerID":["1090867867720278", "104761648907225164100", "114316680403119099502", "103668441331122956874"]
}
can some help me? thanks in advance.
I have an mongoose schema with some properties and subproperties. On the version property I want a subproperty with the Mixed type, because I will send different key/value pairs to this property. But after sending the data to node, the subproperty is empty and is not saved in MongoDB.
This is my Schema
var Product = new mongoose.Schema({
name: {
type: String
},
nameSlug: {
type: String
},
uploader: {
_id: mongoose.Schema.Types.ObjectId,
name: {
type: String,
required: true
}
},
uploadDate: {
type: Date,
default: Date.now,
required: true
},
dateLastModified: {
type: Date,
default: Date.now,
},
isBestseller: {
type: Boolean,
default: false,
required: true
},
isVerified: {
type: Boolean,
default: false
},
suggestedRetailPrice: {
type: Number
},
brand: {
_id: mongoose.Schema.Types.ObjectId,
name: {
type: String,
required: true
},
nameSlug: {
type: String,
required: true
},
images: [Image]
},
productCollection: {
type: String
},
category: {
type: String,
required: true
},
versions: [{
author: [{
name: String,
_id: false
}],
date: {
type: Date,
required: true
},
concept: {
type: Boolean,
required: true
},
modifiedProperties: [mongoose.Schema.Types.Mixed],
history: [{
status: String,
author: [{
name: String,
_id: false
}],
date: Date
}]
}]
}, {strict: false});
module.exports = mongoose.model('Product', Product);
Image an subschema which is not relevant now. On the versions property I have an modifiedProperties property which I want to fill with the changed product (name, nameslug, etc) properties on a update in my Angular application. I create that object as follows
Angular code
var modifiedProperties = [];
angular.forEach($scope.addProductForm, function(value, key) {
if(key[0] == '$') return;
if(value.$dirty){
modifiedProperties[key] = value.$$lastCommittedViewValue;
}
});
var version = {
author: {
name: $rootScope.user.firstName + ($rootScope.user.lastNamePrefix ? " " + $rootScope.user.lastNamePrefix + " " : " ") + $rootScope.user.lastName,
_id: $rootScope.user._id
},
date: new Date(),
concept: true,
modifiedProperties: modifiedProperties,
history: {
author: {
name: $rootScope.user.firstName + ($rootScope.user.lastNamePrefix ? " " + $rootScope.user.lastNamePrefix + " " : " ") + $rootScope.user.lastName,
_id: $rootScope.user._id
},
status: "Versie aangemaakt",
date: new Date()
}
}
console.log("VERSION", version);
var product = $scope.product;
product.versions.push(version);
$api.update('products/' + nameSlug, product)
.then(function(response) {
console.log("response", response);
})
.catch(function(reason) {
console.log(reason);
})
In the console I see the properties correctly filled in, but after a save operation everything but modifiedProperties is saved. I placed some logs in the update function, and what I see is that the modifiedProperties is empty in the controller. I don't know where he lose it's data.
The $api service is our wrapper for the $http function. The data is there not loose, and will we be send using the data field.
The controller
module.exports.updateProduct = function(req, res) {
console.log('[updateProduct controller]');
/* This helper function can be called from elsewhere in the updateProduct controller and processes the HTTP response (and possibly errors) */
function sendResponse(status, response, err) {
/* Log HTTP response to the console server side before actually sending it to the client. */
console.log(status + ' ' + response.message);
/* Also log stack trace on error */
if(err) {
console.log('\nError message: ' + err);
console.log(err.stack);
}
/* Send HTTP response */
res.status(status).json(response);
}
if(req.params && req.params.nameSlug && req.body) {
//Empty modifiedProperties (Array(0))
console.log("REQ", req.body");
let verifyProduct;
if(req.body.verifyProduct && req.body.verifyProduct == true) {
verifyProduct = true;
delete req.body.verifyProduct;
}
console.log("PRODUCT", req.body);
req.body.dateLastModified = Date.now();
Product.findOneAndUpdate({nameSlug:req.params.nameSlug}, req.body, function (err, product) {
/* Some error occurred while trying to update the product. */
if(err) {
sendResponse(400, {message: 'Product could not be added. '}, err);
/* The product doesn't exist */
} else if(!product) {
sendResponse(404, {message: 'Product not found. '});
/* The product exists and has been updated successfully. */
} else {
/* Check if this product is being verified by an admin or not. If so, check if the admin is the same person who initially uploaded the product. */
if(verifyProduct == true && product.uploader._id != req.user._id) {
/* If so, find that user to get their email adress. */
User.findById(product.uploader._id, function(err, user) {
/* An error occurred, so mailing the original uploader is not possible. */
if(err) {
sendResponse(200, {message: 'Product updated with errors. ', product}, err);
/* The original uploader does not exist (anymore), so sending mail is not possible. */
} else if(!user) {
sendResponse(200, {message: 'Product updated, but the uploader doesn`t seem to exist. ', product});
/* Send an email to the original uploader to notify them. */
} else {
var data = {
product: product,
user: user
};
var options = {
to: user.email,
subject: product.en.name + ' is toegevoegd aan PrismaNote!',
template: 'retailer-product-verified'
};
mailService.mail(options, data, null);
sendResponse(200, {message: 'Product updated. ', product});
}
});
} else {
sendResponse(200, {message: 'Product updated. ', product});
}
}
});
}
};
Does anybody know where this can go wrong? Or why this is happen?
Edit:
I see the array modifiedProperties has a length of '0' because of the keys. Is that maybe the reason why nodejs won't proces it?
Hmm, I doesn't still know what is going wrong, but I have solved it, with passing the modifiedProperties directly to product and not in product.versions.
So, my req.body now looks like
name: "testproduct",
nameSlug: "testproduct",
isBestseller: false,
[other properties]
modifiedProperties: {
testfield: "testvalue",
field2: "value2"
},
versions: {
[
date: [today],
concept: true,
[other properties]
],
[
date: [today],
concept: true,
[other properties]
],
}
I would really like some help with this problem, I am sorta stuck. I am trying to manipulate this UserSchema. I want to be able to edit and delete the shippings array within the model but I am having trouble trying to figure out how to access individual items in the array to use an express restAPI. Below is a snippet of the schema and the restAPI endpoint for creating multiple shipping addresses I was able to write. The create endpoint is working but for some reason I am unable to wrap my head around updating and deleting. Any help would be appreciated.
Thanks
var UserSchema = new Schema({
firstname: {
type: String,
default: ''
},
lastname: {
type: String,
default: ''
},
email: {
type: String,
unique: true,
lowercase: true,
},
password: {
type: String,
},
shippings: [{
recipient: {
type: String,
default: ''
},
street: {
type: String,
default: ''
},
city: {
type: String,
default: ''
},
state: {
type: String,
default: ''
},
zip: {
type: String,
default: ''
}
}],
exports.postShipping = function(req, res, next) {
req.assert('recipient', 'Recipient cannot be blank').notEmpty();
req.assert('street', 'Street Address cannot be blank').notEmpty();
req.assert('city', 'City cannot be blank').notEmpty();
req.assert('state', 'State cannot be blank').notEmpty();
req.assert('zip', 'Zip Code cannot be blank').notEmpty();
// req.assert('country', 'Country cannot be blank').notEmpty();
User.findById(req.user.id, function(err, user) {
if (err) return next(err);
var shipping = {};
shipping.street = req.body.street;
shipping.recipient = req.body.recipient;
// shipping.unit = req.body.unit;
shipping.city = req.body.city;
shipping.state = req.body.state;
shipping.zip = req.body.zip;
// shipping.country = req.body.country;
var s = JSON.stringify(shipping);
console.log(s);
var duplicatedShipping = 0;
for (var i in user.shippings) {
console.log(JSON.stringify(user.shippings[i]));
if (JSON.stringify(user.shippings[i]) == s) {
duplicatedShipping = 1;
break;
}
}
if (duplicatedShipping === 0) {
user.shippings.push(shipping);
}
user.save(function(err) {
if (err) return next(err);
console.log(user.shippings);
req.flash('success', {
msg: 'Shipping Address Added'
});
res.redirect('/account/me/shipping');
});
});
I have been googleing this for a few weeks with no real resolution.
I am sure someone will mark this a duplicate, but I am not sure it really is, maybe I am just being too specific, anyway here goes.
I am using angular in a node-webkit app that I am building. I have an api built in express and I am using MongoDB (#mongolab) with Mongoose for the DB.
I had this working fine as long as all of the data types were simple strings and numbers. but I had to restructure the data to use arrays and complex objects. After restructuring the data I was able to get post API calls to work fine, but I cannot get my PUT calls to work at all.
The data looks like this:
itemRoles was an array, but I thought it was throwing the error I am getting now, so I converted it back to a string.
itemStats is causing the problem. Angular is looking for an object, but itemStats is an array (I think anyway). itemStats used to be a string as well, but its easier to work with in my view if it is an array of objects with key:value pairs, which is why I altered it.
I should note I am new to MongoDB as well, first time using it.
{
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bd8"
},
"itemRoles": "healer,dps",
"itemRating": 192,
"itemName": "Advanced Resolve Armoring 37",
"itemClass": "consular",
"itemLevel": 69,
"itemStats": [
{
"name": "Endurance",
"value": 104,
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bda"
}
},
{
"name": "Willpower",
"value": 124,
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bd9"
}
}
],
"__v": 0
}
The Mongoose Schema looks like this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//var stats = new Schema({
//name: String,
//value: Number
//});
var armoringSchema = new Schema({
itemType: String,
itemClass: String,
itemRoles: String,
itemLevel: Number,
itemName: String,
itemRating: Number,
itemStats: [{ name:String, value:Number}]
});
module.exports = mongoose.model('Armor', armoringSchema);
Express API Route:
/ on routes that end in /armors/:id
// ----------------------------------------------------
router.route('/armors/:id')
// get method omitted
// update the armoring with specified id (accessed at PUT http://localhost:8080/api/armors/:id)
.put(function(req, res) {
// use our armor model to find the armor we want
Armoring.findById({_id: req.params.id}, function(err, armor) {
if (err) {
return res.send(err);
}
for(prop in req.body) {
armor[prop] = req.body[prop];
}
// save the armor
armor.save(function(err) {
if (err) {
return res.send(err);
}
res.json({success:true, message: 'Armor updated!' });
});
});
})
Resource Factory:
swtorGear.factory('armoringFactory', ['$resource', function ($resource) {
return $resource('http://localhost:8080/api/armors/:id', {}, {
update: { method: 'PUT', params: {id: '#_id'}},
delete: { method: 'DELETE', headers: {'Content-type': 'application/json'}, params: {id: '#_id'}}
});
}]);
Route for editing:
.when('/edit/armor/id/:id', {
templateUrl: 'views/modelViews/newArmor.html',
controller: 'editArmorCtrl',
resolve: {
armoring: ['$route', 'armoringFactory', function($route, armoringFactory){
return armoringFactory.get({ id: $route.current.params.id}).$promise;
}]
}
})
Contoller (just the save method, the first part of the controller populates the form with existing data):
$scope.save = function(id) {
$scope.armor.itemStats = [
$scope.armor.stats1,
$scope.armor.stats2
];
$scope.armor.itemRoles = '';
if($scope.armor.role.tank) {
$scope.armor.itemRoles += 'tank';
}
if($scope.armor.role.healer) {
if($scope.armor.itemRoles != '') {
$scope.armor.itemRoles += ',healer';
} else {
$scope.armor.itemRoles += 'healer';
}
}
if($scope.armor.role.dps) {
if($scope.armor.itemRoles != '') {
$scope.armor.itemRoles += ',dps';
} else {
$scope.armor.itemRoles += 'dps';
}
}
console.log($scope.armor);
$scope.armor.$update(id)
.then(function(resp) {
if(resp.success) {
var message = resp.message;
Flash.create('success', message, 'item-success');
$scope.armors = armoringFactory.query();
} else {
var message = resp.message;
Flash.create('success', message, 'item-success');
}
});
}
Formatted data being sent via PUT method (from console.log($scope.armor) ):
Error on save:
I haven't seen nesting schemas in the way that you're doing it. Here's something to try (hard to say if this is it for sure, there's a lot going on):
var armoringSchema = new Schema({
itemType: String,
itemClass: String,
itemRoles: String,
itemLevel: Number,
itemName: String,
itemRating: Number,
itemStats: [{
name: String,
value: Number
}]
});
Also we need to pass in an object to $update instead of just a number. Change $scope.armor.$update(id) to $scope.armor.$update({id: id}).
This is working code to populate my Locations collection, which can have self-referencing child Locations. It uses mongoose-deep-populate. But I need to add another ".childLocations" to my path variable for every extra level of depth that I want to handle. Is there a better way to accomplish unknown depths of self-references?
I have this node.js code.
var path = 'childLocations.childLocations.childLocations.childLocations.childLocations.childLocations';
exports.list = function(req, res) {
Location.find().sort('-created').populate('user', 'displayName').deepPopulate(path).exec(function(err, locations) {
console.log(locations);
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(locations);
}
});
};
Here is the schema:
var LocationSchema = new Schema({
name: {
type: String,
default: '',
required: 'Please fill Location name',
trim: true
},
projectsExecutedHere: Boolean,
childLocations: [{
type: Schema.ObjectId,
ref: 'Location'
}],
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Location', LocationSchema);
var deepPopulate = require('mongoose-deep-populate');
LocationSchema.plugin(deepPopulate);
----------
Before trying mongoose-deep-populate, I had seen that mongoose 3.6 had support for deep population, but I could only make it go one level deep. This is what I tried:
Location.find().sort('-created').populate('user', 'displayName').populate('childLocations').exec(function (err, locations) {
Location.populate(locations, {path: 'childLocations.childLocations'},
function (err, data) {
console.log(err);
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(locations);
}
}
);
For the path I also tried 'childLocations.childLocations.childLocations' but it didn't populate it at all.