I want to retrieve the whole model from my database searching by an "id".
Which query is best to use in this case?
This is how my schema looks:
{ _id: 54b5ed4b967a4e3b96fe8a39,
email: 'blabla#yahoo.com',
__v: 0,
deleted: false,
createdAt: Tue Jan 13 2015 23:15:07 GMT-0500 (EST),
shipping: {},
profile: { picture: '', location: 'Romania', name: 'bla' },
tokens: [],
role: 'shopper'}
and what I have is: 54b5ed4b967a4e3b96fe8a39
If you know the type of Model that you are looking for, i.e. Person. Just do:
var id = "54b5ed4b967a4e3b96fe8a39";
Person.findById(id, function(err, person) {
if (err) {
return console.log('oh no! error', err);
}
console.log('found person', person);
});
Documentation here
Related
I use mongoose populate a list of data like:
Account.findOne({_id:accountId}).populate({
path:"orders.order",
match:{_id:orderId},
selecte:'',
options:{
limit:1
}
}).exec(function (err, doc) {
if (err) {
callback(err);
}
callback(doc);
})
}
and what I get:
[ { order: null },
{ order: null },
{ order: null },
{ order: null },
{ order: null },
{ order: null },
{ order:
{ date: Tue May 31 2016 12:56:36 GMT+0800 (HKT),
dishs: [Object],
__v: 0,
message: 'plz deliver after 5 p.m',
price: 5,
address: [Object],
shop: null,
user: 574bfebc29cf722c17f8eafe,
_id: 574d198451615ce01a5e1a81 } } ]
I think this data is an array, but
console.log(typeof doc.orders);//object
console.log(doc.orders.length);//undefined
console.log(doc.orders[0].order);//error
console.log(Array.isArray(doc.orders));//false
I do not know how to delete null value of this data and how to change this data into an array?
By the way, I find a post in gist said that mongoose populate.match will return null value if it did not match the condition, is that true?
I make mistake that I define the schema the wrong way.
The wrong schema:
orders:{order: [{type: mongoose.Schema.Types.ObjectId, ref:'Order'}] }
The right way the define schema in array which you what to populate:
orders:{type:[{
order:{type: mongoose.Schema.Types.ObjectId, ref:'Order'}
}]}
After this, use populate.match will give you an legal array and your could do with it like normal array.
I seem to have an issue with retrieving attributes from a related model.
Models:
// DB = export of Bookshelf
// Signup model
var DB = require('../db').DB;
var UserMeta = require('./usersmeta');
var Signup = DB.Model.extend({
tableName: 'tblSignups',
idAttribute: 'id',
hasTimestamps: true,
usermeta: function() {
return this.belongsTo(UserMeta);
}
});
module.exports = Signup;
// Usermeta model
var DB = require('../db').DB;
var User = require('./users');
var UserMeta = DB.Model.extend({
tableName: 'tblUsersMeta',
idAttribute: 'id',
hasTimestamps: true,
user: function() {
return this.belongsTo(User);
}
});
module.exports = UserMeta;
Admin Signup route:
router.get('/signups', function(req, res, next) {
model.SignUp.fetchAll({withRelated: ['usermeta']}).then(function(collection) {
for(var i = 0; i < collection.toArray().length; i++){
console.log('Signup ' + i + '\n--------------------------');
console.log(collection.toArray()[i]);
console.log('Related usermeta\n--------------------------');
console.log(collection.toArray()[i].related('usermeta'));
}
res.render('admin/pages/signups', {title: 'signups', error: false, signups: collection.toArray()});
}).catch(function(err) {
res.status(500).json({error: true, data: {message: err.message}});
});
});
This is what the console log shows me:
Signup 0
--------------------------
ModelBase {
attributes:
{ id: 2,
usermeta_id: 5,
state: 'pending',
created_at: Thu May 05 2016 17:21:13 GMT+0200 (Romance Daylight Time),
updated_at: Thu May 05 2016 17:21:13 GMT+0200 (Romance Daylight Time) },
_previousAttributes:
{ id: 2,
usermeta_id: 5,
state: 'pending',
created_at: Thu May 05 2016 17:21:13 GMT+0200 (Romance Daylight Time),
updated_at: Thu May 05 2016 17:21:13 GMT+0200 (Romance Daylight Time) },
changed: {},
relations:
{ usermeta:
ModelBase {
attributes: {},
_previousAttributes: {},
changed: {},
relations: {},
cid: 'c38',
relatedData: [Object] } },
cid: 'c35',
id: 2 }
Related usermeta
--------------------------
ModelBase {
attributes: {},
_previousAttributes: {},
changed: {},
relations: {},
cid: 'c38',
relatedData:
RelationBase {
targetTableName: 'tblUsersMeta',
targetIdAttribute: 'id',
type: 'belongsTo',
target:
{ [Function]
NotFoundError: [Function: ErrorCtor],
NoRowsUpdatedError: [Function: ErrorCtor],
NoRowsDeletedError: [Function: ErrorCtor] },
foreignKey: 'tblUsersMetum_id',
parentId: undefined,
parentTableName: 'tblSignups',
parentIdAttribute: 'id',
parentFk: undefined } }
So as you can see the related model attributes is empty. I saved my usermeta as follows:
userMeta.save().then(function(usermeta) {
var signup = new model.SignUp({
usermeta_id: usermeta.attributes.id
});
signup.save().then(function() {
req.flash('success', 'Success!');
res.redirect('/signup');
}).catch(function(err) {
res.status(500).json({error: true, data: {message: err.message}});
});
}).catch(function (err) {
res.status(500).json({error: true, data: {message: err.message}});
});
Within the database the usermeta's id (in the signup table) is set correctly. What am I doing wrong here?
It appears that something is wrong with your models. When you're setting up the relation between the models you use belongsTo in both examples - that can't be right. I don't know what is the relation between them (many-to-many? one-to-many?). If it's many-to-many you need to use belongsToMany and if it's one-to-many you need to set hasMany on the model that does not hold the foreign key in the database and belongsTo to the model that has the foreign key in the database.
See this http://bookshelfjs.org/#one-to-many and this http://bookshelfjs.org/#many-to-many
Hope this helps!
I am trying to make a populate query with mongodb (using mongoose as orm), and it doesn´t work 100%. I mean that I get all the entries from the document where I apply the populate... ALL, the entries that (on the crossed document) match with the match query (and I obtain a nested object), but I get the others too (and the nested object is null).
This is what I have done:
MODELS
var userSchema = Schema({
name: String,
email: String,
idiom: String
});
var ticketsSchema = Shema({
user_id:{ type:Schema.Types.ObjectId, ref:'User', required: true},
date: Date,
points: Number,
kart: String
});
POPULATE
tickets.find()
.populate(
{
path: 'user_id',
match:{name:"user1"}
}
).exec(function (err, result) {
if (err) return handleError(err);
res.send(result);
});
And a possible result could be:
Object[0]
__v: 0
_id: "5655b68ccbe953bc2a78da54"
date: "2015-11-25T13:24:28.561Z"
date: "2015-11-25T13:24:28.561Z"
points: 50
kart: "Senior"
user_id: Object
__v: 0
_company: 0
_id: "5655b656cbe953bc2a78da53"
name: "user1"
email: "user1#mail.com"
idiom: "es"
Object[1]
__v: 0
_id: "5655b732e0685c441fddb99b"
date: "2015-11-25T13:27:14.608Z"
points: 75
kart: "Pro Senior"
user_id: Object
__v: 0
_company: 0
_id: "5655b656cbe953bc2a78da53"
name: "user1"
email: "user1#mail.com"
idiom: "es"
Object[2]
__v: 0
_id: "56564613701da2981aa017d6"
date: "2015-11-25T23:36:51.774Z"
points: 75
kart: "Pro Senior"
user_id: null
Object[3]
__v: 0
_id: "565646ee701da2981aa017d8"
date: "2015-11-25T23:40:30.308Z"
points: 75
kart: "Pro Senior"
user_id: null
This isn´t exactly what I want to do... I would want that the two last doesn´t show up.
EDIT
I think I didn´t explain clear myself clearly... what I want to do is a JOIN query...
I have seen that I need use a mapreduce, I tried to do but I don´t found a place where it is explained for... dummies. All what I could do until now is this:
ticketsDB.find()
.populate(
{
path: 'user_id',
match:req.body
}
).exec(function (err, result) {
if (err) return res.send(err);
reslt=[];
for(var i in result)
if(result[i].user_id)reslt.push(result[i]);
console.log(reslt);
res.send(reslt);
});
Thank you.
Thanks #JohnnyHK by his comment, I found the solution here: Mongoose nested query on Model by field of its referenced model
And now the code is something like:
usersDB.find(req.body, function(err, docs) {
var ids = docs.map(function(doc) { return doc._id; });
ticketsDB.find({user_id: {$in: ids}})
.populate('user_id').exec(function (err, result) {
if (err) return res.send(err);
reslt=[];
for(var i in result)
if(result[i].user_id)reslt.push(result[i]);
res.send(reslt);
});
});
Where req.body is {name:"user 1"} or {email:"user1#user.com"}.
EDIT
I was thinking a little (sorry, it will happen no more ;p ), and I think that there is a way to remove the mapping of this query. Now my answer is this:
usersDB.find(req.body).distinct("_id", function(err, docs) {
ticketsDB.find({user_id: {$in: docs}})
.populate('user_id').exec(function (err, result) {
if (err) return res.send(err);
reslt=[];
for(var i in result)
if(result[i].user_id)reslt.push(result[i]);
res.send(reslt);
});
});
Could be that valid??
I have a model like this:
User:
{
name: "test",
phone: "1234567890",
password: "test",
email: "test#tester.com",
tasks: {
{ task: "do this", timestamp: "2015-08-01" },
{ task: "then this", timestamp: "2015-08-05" },
{ task: "finally this", timestamp: "2015-08-07" }
}
},
... (more users) ...
How can I get a specific user's details like name, email, and only 1 task the latest one?
User.find({phone: '1234567890', password: 'test'}, '_id name email tasks', function(err, user) {
if (err)
res.json({result: false});
res.json({result: !(user == null), object: user});
});
This returns all the tasks.
You could use $slice (projection)
User.find({
phone: '1234567890',
password: 'test'
}, {
name: 1,
email: 1,
tasks: {$slice: -1}
}, function (err, user) {
if (err) {
res.json({result: false});
return;
}
return res.json({result: !(user == null), object: user});
});
Note that tasks should be Array but not Object.
if you are inserting new task by push method of array. then you can get last record by getting length of tasks array and access last record by length - 1.
or you can refer this :
return document with latest subdocument only in mongodb aggregate
This is my Schema:
var userschema = new mongoose.Schema({
user: String,
imagen: [{
name: String,
author: String,
date: { type: Date, default: Date.now },
}],
follow: [String]
});
And this is the code:
usermodel.findOne({ user: req.session.user }, function (err, user){
usermodel.find({ _id: {$in: user.follow } }, function (err, images){
console.log(images);
if (err) throw err;
res.render('home.ejs', {
user: user,
following: images
});
});
});
The follow array in the Schema contains the _ids of the users that the actual user is following. I'm trying to get an output like this:
{ _id: 50fd9c7b8e6a9d087d000006,
imagen:
[ { name: 'fff.png',
author: 'foo',
_id: 50fd9ca2bc9f163e7d000006,
date: Mon Jan 21 2013 20:53:06 GMT+0100 (CET) },
{ name: 'mmm.png',
author: 'foo',
_id: 50fda83a3214babc88000005,
date: Mon Jan 21 2013 21:41:34 GMT+0100 (CET) } ] },
{ _id: 50fd9d3ce20da1dd7d000006,
imagen:
[ { name: 'ddd.jpg',
author: 'faa',
_id: 50fda815915e068387000005,
date: Mon Jan 21 2013 21:42:57 GMT+0100 (CET) } ] }
And I'm trying to get an output similar at this, for example:
{ [ { name: 'fff.png',
author: 'foo',
_id: 50fd9ca2bc9f163e7d000006,
date: Mon Jan 21 2013 20:53:06 GMT+0100 (CET) },
{ name: 'ddd.png',
author: 'faa',
_id: 50fda815915e068387000005,
date: Mon Jan 21 2013 21:42:34 GMT+0100 (CET) },
{ name: 'mmm.png',
author: 'foo',
_id: 50fda83a3214babc88000005,
date: Mon Jan 21 2013 21:41:34 GMT+0100 (CET) }
] }
I think that what I want is imposible, or very complex, is there any solution for this...?
Thank's advance!
In this line:
usermodel.find({ _id: {$in: user.follow } }, function (err, images){
images is not good name, nicer name is users or even docs (you'll have an array of documents of usermodel schema there). So images in your code are found documents.
I've made a little test with the same schema as you gave. Here is the part where I join all user.imagen arrays and then sort them (of course it is test case but it works, hope this will lead you to the right way):
User.find {}, (err, users) ->
all_images = []
# iterate users array to join all imagen arrays
for user in users
all_images.push user.imagen
# flatten nested arrays in all_images with underscore function
all_images = _.flatten all_images
# sort all_images the way you want (i.e. descending)
all_images.sort (a, b) -> b.date - a.date
# render page and see that it works
res.render 'test.html', {images: all_images}