Packing data with mongoose - node.js

I have 3 files with different schema. User has many notebooks and notebooks has many notes. Example of schemas :
UserSchema:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var User = new Schema({
username: { type: String, require: true, index: { unique: true }, trim: true},
password: { type: String, require: true, select: true },
age: { type: Number, min: 0 },
firstname: String,
secondname: String,
token: String,
role: String,
city: String,
rememberMe: Boolean
});
module.exports = mongoose.model('User', User);
NotebookSchema:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
Note = require('./note'),
User = require('./user');
var NoteBook = new Schema({
creator: { type:Schema.ObjectId, ref:"User"},
name: String,
description: String
});
NoteBook.methods.getAllNotes = function(cb) {
Note.find({notebook: this}, function(err, noteList){
cb(noteList);
});
};
module.exports = mongoose.model('NoteBook', NoteBook);
NoteSchema:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var NoteSchema = new Schema({
notebook: { type: Schema.Types.ObjectId, ref: 'NoteBook'},
name: String,
description: String,
content: String
});
module.exports = mongoose.model('Note', NoteSchema);
I get in request userId and I need to pack json all this line of data. User with Notebooks and Notebooks with note in one json. I triyed something like this:
function getTree(req, res) {
var data = [];
User.findOne({_id: req.body.userId}, function(err, user) {
NoteBook.find({creator: user._id}, function(err, notebookList) {
for (var idx in notebookList) {
Note.find({notebok: notebookList[idx]._id}, function(err, noteList) {
var children = [];
for (var noteIdx in noteList) {
children.push({
'text': noteList[idx].name,
'a_attr' : {
'data-node-type': 'note',
'data-node-id': noteList[idx]._id,
},
});
}
data.push({
'text': notebookList[idx].name,
'a_attr' : {
'data-node-type': 'notebook',
'data-node-id': notebookList[idx]._id,
},
'children': children
});
});
}
res.json({ tree: data });
});
});
}
but it doesn't work.

var async = require("async");
function getTree(req, res) {
var data = [];
User.findOne({_id: req.body.userId}, function(err, user) {
NoteBook.find({creator: user._id}, function(err, notebookList) {
async.forEach(notebookList, function(notebook, callback){
Note.find({notebok: notebook._id}, function(err, noteList) {
var children = [];
for (var noteIdx in noteList) {
children.push({
'text': noteList[idx].name,
'a_attr' : {
'data-node-type': 'note',
'data-node-id': noteList[idx]._id,
},
});
}
data.push({
'text': notebookList[idx].name,
'a_attr' : {
'data-node-type': 'notebook',
'data-node-id': notebook._id,
},
'children': children
});
});
}, function(err){
res.json({ tree: data });
});
});
});
}

Related

Validation error when creating a mongodb using mongoose

I am having difficulty with saving into a mongodb using mongoose. Here is the error i am getting
Application has thrown an uncaught exception and is terminated:
ValidationError: pageModel validation failed
my code
//page.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var pageShema = new Schema({
pageId: {
type: String,
required: true
},
logo: {
type: String
},
subline: {
type: String
},
header: {
type: String
},
created_on: {
type: Date,
default: Date.now
},
offense:{
type: Schema.Types.Mixed
},
deffense:{
type: Schema.Types.Mixed
}
});
var pageModel = mongoose.model('pageModel', pageShema);
module.exports = pageModel;
app.js
var mongoose = require('mongoose');
var dbURL = config.dbURL;
mongoose.connect(dbURL);
var pagedb = require('./models/page');
var page = new pagedb( {
pageId: 'test',
logo:'test logo',
subline: 'test subline',
header: 'test header',
created_on: Date.now,
offense: {},
deffense: {}
});
page.save(function (err, page) {
if (err) {
console.log('error!');
throw err;
};
console.log('page is created!');
});
It fails because of the date field. Use new Date() instead of Date.now.
var mongoose = require('mongoose');
var dbURL = config.dbURL;
mongoose.connect(dbURL);
var pagedb = require('./models/page');
var page = new pagedb( {
pageId: 'test',
logo:'test logo',
subline: 'test subline',
header: 'test header',
created_on: new Date(),
offense: {},
deffense: {}
});
page.save(function (err, page) {
if (err) {
console.log('error!');
throw err;
};
console.log('page is created!');
});

Mongo db, how to give object _id another collection's document

I have 2 collections called User and Location. In User, there is a location _id and this is an Object. Id also references the location collection. My question is what did I do wrong? When I call getUser function I want to see user information and the user's location information. What I need to do ?
User Schema
module.exports = (function userSchema() {
var Mongoose = require('mongoose');
var userSchema = Mongoose.Schema({
name: {
type: String,
require: true
},
surname: {
type: String,
require: true
},
tel: {
type: String,
require: true
},
age: {
type: String,
require: true
},
mevki_id: {
type: String,
require: true
},
location_id: [{
type: Mongoose.Schema.Types.ObjectId,
ref: 'locations'
}]
});
var collectionName = 'users';
var User = Mongoose.model(collectionName, userSchema);
return User;
})();
User Controller
function userController() {
var User = require('../models/UserSchema');
this.createUser = function (req, res, next) {
var name = req.body.name;
var surname = req.body.surname;
var tel = req.body.tel;
var age = req.body.age;
var mevki_id = req.body.mevki_id;
var lok_id = req.body.lok_id;
User.create({
name: name,
surname: surname,
tel: tel,
age: age,
mevki_id: mevki_id,
lok_id: lok_id
}, function (err, result) {
if (err) {
console.log(err);
return res.send({
'error': err
});
} else {
return res.send({
'result': result,
'status': 'successfully saved'
});
}
});
};
this.getUser = function (req, res, next) {
User.find()
.populate('lok_id')
.exec(function (err, result) {
if (err) {
console.log(err);
return res.send({
'error': err
});
} else {
return res.send({
'USERS': result
});
}
});
};
return this;
};
module.exports = new UserController();
First, your schema is wrong:
var userSchema = new Mongoose.Schema({
// ...
location_id: { type: [Mongoose.Schema.Types.ObjectId], ref: 'locations' }
})
Second, in your schema the last field name is location_id while in your controller, you change it to lok_id.
So, fix this:
User.create({
// ...
location_id: lok_id
}
and this:
User
.find()
.populate('location_id')
UPDATE
In your json the last field name is location_id, therefore, fix this too:
this.createUser = function (req, res, next) {
// ...
var lok_id = req.body.location_id;
}

Mongodb two collections aggregation

players schema:
var mongoose = require('mongoose'),Schema = mongoose.Schema;
var playerSchema = new mongoose.Schema({
name: String,
password: String,
country: [{ type: Schema.Types.ObjectId, ref: 'countries' }]
});
mongoose.model('players', playerSchema);
countries schema:
var mongoose = require('mongoose'),Schema = mongoose.Schema;
var countrySchema = Schema({
name: String,
isActive: Boolean
});
mongoose.model('countries', countrySchema);
And this is my node js find query:
router.route('/')
.get(function(req, res, next) {
mongoose.model('players').find().populate('country').exec(function (err, players) {
console.log(players);
if (err) {
return console.error(err);
} else {
res.format({
html: function(){
res.render('players/index', {
title: 'Players',
"players" : players
});
},
json: function(){
res.json(players);
}
});
}
});
});
I want the result set with countryId and name . But I got country is null.What to do ?

Why is mongoosastic populate / elastic search not populating one of my references? I'm getting an empty object

I have two models I'm attempting to reference. Style and Brand.
Brand populates with the needed object, but Style is always empty.
i've tried clearing cache / deleting indexes. With and without include_in_parent and type: 'nested'.
I feel it may have something to do with the specified es_type, etc.. not sure.
Product Schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Style = require('./style');
var Brand = require('./brand');
var mongoosastic = require('mongoosastic');
var ProductSchema = new mongoose.Schema({
name: { type: String, lowercase: true , required: true},
brand: {type: mongoose.Schema.Types.ObjectId, ref: 'Brand',
es_type:'nested', es_include_in_parent:true},
style: {type: mongoose.Schema.Types.ObjectId, ref: 'Style',
es_schema: Style, es_type:'nested', es_include_in_parent: true},
year: { type: Number }
});
ProductSchema.plugin(mongoosastic, {
hosts: [
'localhost:9200'
],
populate: [
{path: 'style'},
{path: 'brand'}
]
});
Product = module.exports = mongoose.model('Product', ProductSchema);
Product.createMapping(function (err,mapping) {
if(err){
console.log('error creating mapping (you can safely ignore this)');
console.log(err);
}else{
console.log('product mapping created!');
console.log(mapping);
}
});
var stream = Product.synchronize();
var count = 0;
stream.on('data', function(){
count++
});
stream.on('close', function(){
console.log('indexed whisks ' + count + " documents");
});
stream.on('error', function(){
});
style schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongoosastic = require('mongoosastic');
var StyleSchema = new mongoose.Schema({
name: { type: String, lowercase: true , required: true},
});
Style = module.exports = mongoose.model('Style', StyleSchema);
Style.createMapping(function(err, mapping){
if(err) console.log('error w/ mapping : ', err);
console.log('mapping created');
console.log(mapping);
})
var stream = Style.synchronize();
var count = 0;
stream.on('data', function(){
count++
});
stream.on('close', function(){
console.log('indexed styles ' + count + " documents");
});
stream.on('error', function(){
});
search query:
exports.topSearch = function(req, res) {
console.log(req.body, "search product")
Product.search({query_string: {query: req.body.search}}, {from: req.body.fromNum,
size: req.body.size,
hydrate: req.body.hydrate
},
function(err, results) {
if (err) console.log('ERR', err);
if (results){
var data = results.hits.hits.map(function(hit) {
return hit
});
console.log('product data', data)
res.send(data);
}
else {
res.send({errmsg:'results not defined'})
}
});
};
When I query, I get this result in a hit:
_source:
{ name: 'Redemption White Rye Whiskey',
brand: [Object],
style: {},} },
regarding comment request:
Product being added to DB:
exports.create = function(req, res) {
Product.create(req.body, function(err, product) {
if (err) {
console.log('ERR', err)
};
res.send({
product: product
});
});
};
front / angular:
$scope.add = function () {
var prodStyle = JSON.parse($scope.selectedStyle);
$scope.product = $scope.product._id;
$scope.product.style = prodStyle._id;
console.log($scope.product.style, 'prod style');
Product.create($scope.product).then(function (res) {
res.data.product.style = { name: prodStyle.name };
$scope.products.push(res.data.product);
$scope.product = {};
$scope.selectedStyle = {};
});
};
I've got it working, but it differs much from the examples given on npm / github.
I had to remove the es_schema: Style, (as I had accidentally done for brand, which was why it worked). I had to add the es_type: "nested" / es_include_in_parent, which I gathered from elasticsearch and mongoosastic documentation.
I'm not sure this is intended, but it seems to work:
style: {type: mongoose.Schema.Types.ObjectId, ref: 'Style',
es_type:'nested', es_include_in_parent:true},
I now get : style: [Object] as needed, when I console.log results.hits .
Below is the example given in npm , which did not work for me:
var Comment = new Schema({
title: String
, body: String
, author: String
});
var User = new Schema({
name: {type:String, es_indexed:true}
, email: String
, city: String
, comments: {type: Schema.Types.ObjectId, ref: 'Comment',
es_schema: Comment, es_indexed:true, es_select: 'title body'}
})
User.plugin(mongoosastic, {
populate: [
{path: 'comments', select: 'title body'}
]
})

Retrieve Documents containing a subdocument in a REST API

I am trying to retrieve a list of documents that contain a sub doc to be listed on a web application.
I have my models setup as such:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var storeSchema = new mongoose.Schema({
name: String,
address: String,
phone: String,
webUrl: String,
coords: {type: [Number], index: '2dsphere'}
});
var reviewSchema = new mongoose.Schema({
user: {type: String, required: true},
store: { type: Schema.ObjectId, ref: 'Store' },
review: {type: String},
tags: [String]
});
mongoose.model('Review', reviewSchema);
mongoose.model('Store', storeSchema);
And the api controller setup as such:
var mongoose = require('mongoose');
var Game = mongoose.model('Review');
var sendJsonResponse = function(res, status, content) {
res.status(status);
res.json(content);
};
module.exports.gamesListByDistance = function(req, res) {
var lng = parseFloat(req.query.lng);
var lat = parseFloat(req.query.lat);
var maxDistance = parseFloat(req.query.maxDistance);
var point = {
type: "Point",
coordinates: [lng, lat]
};
var geoOptions = {
spherical: true,
maxDistance: theEarth.getRadsFromDistance(maxDistance),
num: 10
};
Review.geoNear(point, geoOptions, function(err, results, stats) {
console.log('Geo Results', results);
console.log('Geo stats', stats)
if (err) {
console.log('geoNear error:', err);
sendJsonResponse(res, 404, err);
} else {
results.populate(results, {path:'store', select:'name coords'}, function(err,reviews) {
if (err) {
sendJsonResponse(res, 400, err);
} else {
games = buildReviewsList(req, res, results, stats);
sendJsonResponse(res, 200, reviews);
}
});
}
});
};
var buildReviewsList = function(req, res, results, stats) {
var reviews = [];
results.forEach(function(doc) {
reviews.push({
distance: theEarth.getDistanceFromRads(doc.dis),
store: doc.obj.store.name,
status: doc.obj.status,
tags: doc.obj.tags,
_id: doc.obj._id
});
});
return reviews;
};
But am getting:
TypeError: undefined is not a function
What is the proper way to populate these subdocs and return the list of reviews to be consumed with a Web Application?
Why do you have :
var Game ?
should be var Review.

Resources