MongoDB with Mongoose aggregate data - node.js

I have problems with aggregating data:
//create a schema
var userSchema = new Schema (
{
Anzahl: Number,
Art: String,
Gewicht: Number,
Strecken_ID: Number,
}, {collection: 'kkr'});
//model
var User = db.model('User', userSchema);
//test aggregate
app.get('/gesamt', function(req,res){
User.aggregate([{"$match": {Art: "Aal"}}], function(err, docs){
if(err){console.log(err);}
else {res.json(docs);}
});
});
This delivers an empty array []; what ist the reason?
Any help would be great.
Best
Hucho

[] means there is no documents with value Art: "Aal" in kkr collection.

Related

Is there a way to edit mongo db sorting?

I have a mongoose collection that sorts by first added, and I want it to sort by last edited
The model
var mongoose = require("mongoose");
var user = require("./user");
var questionSchema = new mongoose.Schema({
text: String,
asked: String,
answer: String
})
module.exports = mongoose.model("question", questionSchema);
The put request code:
router.put("/:user/:id", checkOwner, function(req, res){
question.findByIdAndUpdate(req.params.id, req.body.question, function(err,
updatedQuestion){
if(err) {
console.log(err);
} else {
res.redirect("/");
}
});
});
I want that updatedQuestion to be on the top my collection
Here is one simple approach:
First you have to add timestamps in your mongoose model, in order to have access on createdAt and updatedAt proerties.
You can see more about timestamps here
var mongoose = require("mongoose");
var user = require("./user");
var questionSchema = new mongoose.Schema({
text: String,
asked: String,
answer: String
},
{ timestamps: true}
)
module.exports = mongoose.model("question", questionSchema);
Then you can query your collections, applying sorting by updatedAt
question.find({}, {}, {sort: { 'updatedAt' : -1 }})
Thus the most recent updated document will be shown first.

Nodejs: Create search query with reference collection field

My User collection model schema:
var userModel = new Schema({
userAddress: { type: Object, ref: 'useraddress' },
name: String,
});
My User addresses collection model schema:
var addressModel = new Schema({
macAddress: String,
repeat: Number,
});
Get data method is:
module.exports.get = function (req, res) {
var _repeatTime = 2;
var _searchQRY = [];
_searchQRY.push(
{
"useraddress.repeat": { $gte: _repeatTime}
});
userModel.find({ $and: _searchQRY }).populate('useraddress').exec(function (err, results) {
res.json({ record: results})
});
This is my code. I want to filter with address repeat number. But i am not getting correct result with this query.
First Mongoose performs the the search on users collection by {"useraddress.repeat": {$gte: val}} query. And only after the call starts population.
So you should get 0 results as address is not yet populated.
Here are 2 ways of solving this. First, check out this answer please.
You'll need to:
//Any conditions that apply to not populated user collection documents
var userQuery = {};
userModel.find(userQuery)
//Populate only if the condition is fulfilled
.populate('useraddress', null, {"useraddress.repeat": { $gte: _repeatTime}})
.exec(function (err, results) {
results = results.filter(function(doc){
//If not populated it will be null, so we filter them out
return !!doc.useraddress;
});
//Do needed stuff here.
});
The second way is to use aggregation and $lookup (you'll need mongodb v 3.2+). Basically it means to move this population and filtering to DB level.
userModel
.aggregate()
//Anything applying to users collection before population
.match(userQuery)
.lookup({
from: 'address', //Please check collection name here
localField: 'useraddress',
foreignField: '_id',
as: 'useraddress'
})
//Lookup pushes the mathes to an array, in our case it's 1:1, so we can unwind
.unwind('useraddress')
//Filter them as you want
.match({'useraddress.repeat': { $gte: _repeatTime}})
.exec(function (result) {
//Get the result here.
});

what is the Mongoose find query using nodejs?

This is my players model
var mongoose = require('mongoose'),Schema = mongoose.Schema;
var playerSchema = Schema({
name: String,
password: String,
country: String
});
mongoose.model('players', playerSchema);
This is my countries model
var mongoose = require('mongoose'),Schema = mongoose.Schema;
var countrySchema = Schema({
name: String,
isActive: Boolean
});
mongoose.model('countries', countrySchema);
And this is app.js
mongoose.model('players').find({}, function (err, players) {
console.log(players);
if (err) {
return console.error(err);
} else {
res.format({
html: function(){
res.render('players/index', {
title: 'Players List',
"players" : players
});
},
json: function(){
res.json(players);
}
});
}
});
In players model I have countryId and in countries model I have corresponding countryName. Now I want to find players with country name with same find() query.
you can use mongoose populate method
refer this link: mongoose populate
in your example, it something like this:
mongoose.model('players').find().populate('country').exec(function(err,players){
});
this will give you result of both countryID and Name
mongodb is nosql-database, not a relational database like mysql/postgre. So modelling your data is not like relationaldatabses where you can make one query that joins two tables (in mongodb, "tables" are called collections).
In MongoDB and your current Schema you will first need to find the countryId of the country you want. And then find the players that have that country.
Alternatives;
you can store the countryName directly on the player collection
you can store the playerId's in an array within the the country collection
further more, in your playerSchema, country should be a ObjectId, not a String.

Mongoose - inserting subdocuments

I have a user model, and a log model. The log model is a subdocument of user model. So in my user model I have:
var mongoose = require('mongoose');
var Log = require('../models/log');
var UserSchema = new mongoose.Schema({
username: {
type: String,
unique: true
},
logsHeld: [
Log
]
});
Then in my 'Log' model I have:
var mongoose = require('mongoose');
var logSchema = new mongoose.Schema({
logComment: {
type: String,
},
});
module.exports = mongoose.model('Log', logSchema);
So upon creation of a 'user', the 'logsHeld' always begins empty. I want to know how to add subdocuments to this user model.
I've tried doing this POST method:
router.post('/createNewLog', function(req, res) {
var user = new User ({
logssHeld: [{
logComment: req.body.logComment
}]
});
user.save(function(err) {
if(err) {
req.flash('error', 'Log was not added due to error');
return res.redirect('/home');
} else {
req.flash('success', 'Log was successfully added!');
return res.redirect('/home');
}
});
});
But this doesn't work. It also includes a 'new User' line, which I don't think I need given this would be for an existing user.
You need to use the logSchema instead of the Log model as your subdocument schema in User model. You can access the schema as follows:
var mongoose = require('mongoose');
/* access the Log schema via its Model.schema property */
var LogSchema = require('../models/log').schema; // <-- access the schema with this
var UserSchema = new mongoose.Schema({
username: {
type: String,
unique: true
},
logsHeld: [LogSchema]
});
Picking up from your comments in another answer where you are facing another issue
WriteError({"code":11000,"index":0,"errmsg":"E11000 duplicate key
error index: testDB.users.$email_1 dup key:
you are getting this because there's already a document in your users collection that has most probably a null value on the email field. Even though your schema does not explicitly specify an email field, you may have an existing old and unused unique index on users.email.
You can confirm this with
testDB.users.getIndexes()
If that is the case and manually remove the unwanted index with
testDB.users.dropIndex(<index_name_as_specified_above>)
and carry on with the POST to see if that has rectified the error, I bet my $0.02 that there is an old unused unique index in your users collection which is the main issue.
Try using logSchema which references only the subdocument schema, Log refers to the entire contents of ../models/log
var UserSchema = new mongoose.Schema({
username: {
type: String,
unique: true
},
logsHeld: [
logSchema
]
});
Documentation: http://mongoosejs.com/docs/subdocs.html
Try push to insert item in array in mongoose
var user = new User;
user.logssHeld.push({
logComment: req.body.logComment
});
user.save(function(err, doc) {
//DO whatever you want
});
see the docs here

Mongoose returning empty array of ObectID, which isn't

I am using the following Mongoose Schema :
var userSchema = new mongoose.Schema({
...
sentFriendsRequests: [{
type : ObjectId,
}]
)};
I am adding some ObjectIds to the sentFriendsRequests
User.update({ _id: userId },
{ $push: { sentFriendsRequests: targetId }},
{safe: true, upsert: true}, function(err, result) {
if (err || !result) {
done(err);
}
done(null);
});
This seems to be working properly, because as I am using Mongolab to host my Database, when displaying documents on screen I can see that the ObjectIds are added to the array with success :
"receivedFriendsRequests": [
"5720c659571a718705d58fc3"
]
The weird thing is that when querying this array, Mongoose always return an empty one...
User.find({ _id: userId}, function(err, res) {
console.log(res[0].sentFriendsRequests);
});
// prints []
Have confusion of mongodb with mongoose.
Mongoose need define Schema but mongodb is nope.
To define new ObjectId in mongodb:
var ObjectId = require('mongodb').ObjectID
var objectId = new ObjectID();
in Mongoose:
var mongoose = require('mongoose');
var objectId = new mongoose.Types.ObjectId;
I finally found that using var ObjectId = require('mongodb').ObjectID; makes Mongoose to return empty array, whereas using mongoose.Schema.Types.ObjectId works properly. I don't know how to explain this.

Resources