I am trying to attach the full user model to each comment in my comments section. Since mongodb doesn't have joins I have been trying to figure out how to use .populate() to add the user object from the controller. As I understand it, to use the populate function there are only two things you must do.
Define a ref in the model.
Call .populate() on the name of the field which has a ref defined.
I have defined the ref in the model to the 'User' model:
var commentSchema = new mongoose.Schema({
author: { type: String, ref: 'User' },
description: String,
commentID: String,
hasParent: String,
parentComment: String,
timestamp: { type: Number, default: 0 },
});
Then I am trying to add the user model to the author field in the comment object:
Comment
.find()
.populate('author')
.exec(function (err, comments) {
console.log(comments);
});
Is there a step that I am missing? I was hoping to see all the comments with the full user object in the author field of each comment.
The solution was deleting the comments collection from mongodb. Starting fresh it works as expected. If anyone runs into a similar problem try deleting the collection of objects that were created before you had added a ref to the model.
Please consider making following changes.
author: { type: String, ref: 'User' };
authot: { type: Schema.Types.ObjectId, ref:'User'};
Related
Problem
I have an ObjectId saved in a field -incomingFriendRequests- and I want to move it to another field -friends-.
Is there a better way to do this than to remove it from receivedFriendRequests and then do an findOneAndUpdate to add it to friends? I feel like this can be accomplished with one database call instead of two.
Code
Mongoose Model:
const userSchema = mongoose.Schema({
friends: [{
type: mongoose.Schema.Types.ObjectId, ref: 'User', require: false
}],
incomingFriendRequests:[{
type: mongoose.Schema.Types.ObjectId, ref: 'User', require: false
}],
online: {type: Boolean, require: true}
});
It is not possible in a single query you need to first perform $pull on the incomingFriendRequests field for remove selected objectId and then you need to perform another update query on friends for add selected objectId. also, you can use $addToSet to preventing duplication id. if you use $push for add in that case duplicate objectId also store.
Query :-
1) Remove :- db.getCollection('testdata').update({id:ObjectId('5cc3fa66a04275096417f9ca')},{"$pull":{"incomingFriendRequests":"5cc3fa66a04275096417f9da"}}});
2) add :-
db.getCollection('testdata').update({id:ObjectId('5cc3fa66a04275096417f9ca')},{"$addToSet":{"friends":"5cc3fa66a04275096417f9da"}}); // also you can use $push
Moving values from one field to another would definitely need n + 1 calls to do the transformation. This can be achieved using
find({}).forEach(function(doc) {
// your doc update
doc.save();
});
Or you can even perform a bulkwrite.
In case if your goal is to delete the column incomingFriendRequests, you can probably rename the column to friends instead copying all the data.
update({}, { $rename: {incomingFriendRequests: friends }});
I´m using MongoDB and mongoose for a project that needs to track data creation and changes. The requirements are that I need to keep track of records creation and changes including the date/time and the application user (not the OS user) who did it.
I´ve seen the mongoose timestamps option that would solve my date/time issue, but is there a way to extend it to include extra properties, where I´m gonna be adding the application username ?
If not, is there a single place where I can write a function that will be called on every creation/update so that I can include/modify these fields ?
Today I´m insering these properties on every model like below, but I would like to move all of them to a single place.
var companySchema = mongoose.Schema({
name: {
type: String,
index: true
},
phone: {
type: String
},
deleted: {
type: Boolean
},
createdAt: {
type: Date
},
createdBy: {
type: String
},
updatedAt: {
type: Date
},
updatedBy: {
type: String
}
});
How would be the best approach for it ?
I would approach it by creating two models, one for each Data created, one for each Data Changes.
Data created which will have 6 fields one is createdBy, createdAt, and one will be a field with an array of reference id of Data Changes, deletedBy, deletedAt, deletedFlag.
Data Changes will have fields dataID which will have reference id of data created, updatedBy and updatedAt.
This way it will be easy to keep track of when it was created when it was changes and when it was deleted.
PS: You can remove either of Array in Data created model or dataID ref id in Data Change mode, it was just me being extra cautious while binding.
I'm using Mongoose ODM to partially validate models before they are stored to MongoDB.
Is it possible to relax Mongoose schemata so that a given part of the document is not validated? I have tried to the following:
var MySchema = new Schema({
user_id: { type: Schema.ObjectId, ref: 'User' },
freeform_data: {},
});
For instance if I set the contents to:
{
user_id: '123456',
freeform_data: {
dataitem1: 'a',
dataitem2: 'b',
items: [ 1, 2, 3, 4 ]
}
}
Then only user_id is stored, which makes perfectly sense security-wise.
How can I disable mongoose's validation for this field?
I am using this application only for prototyping purposes so I don't care about security right now (I just want to prototype).
When you modify the contents of a Mixed field like freeform_data, you need to notify Mongoose that you've changed its value by calling markModified(path) on the modified document or a subsequent save() call won't save it.
For example:
user.freeform_data = { foo: 'bar' };
user.markModified('freeform_data');
user.save();
Mongeese
: a mongoose multi-database helper/hack module
https://github.com/donpark/mongeese
Disclaimer: I was looking to connect to two MongoDB instances in the same app and gave up. So I haven't tried it.
I got some problems with a certain mongoose query.
Imaging having a schema like so
var Task = new Schema({
title: String,
createdBy: {
type: Schema.Types.ObjectId, ref: 'User'
},
pool: [{
userId: {type: Schema.Types.ObjectId, ref: 'User'},
accepted: {
type: Boolean,
default: false
}
}]
});
Task.find({pool: {$elemMatch:{userId: userId, accepted: false}}}, {'pool.$':1}).populate('createdBy', '_id name surname').populate('pool.userId', '_id name surname').exec(function(err, tasks){
So now the thing is I really just get the array entry I want but i don't get the rest of the Document like title and createdBy.
Anyone any suggestions how to solve this?
Kind regards Thomas
Oh sorry my bad I don't have the keyword var in my schema. I was in such a hurry creating my question. So here again. I am using elemMatch to find a document by a criteria found in an Array. It works very well returning just the found array element. What I want thou is that it returns the whole document like 'title and createdBy and pool' but in pool just the one element matching the elemMatch criteria.
I hope my question is now more understandable.
Kind regards and thanks for your help
Remove the keyword var from title and createdBy.
Reason: Schema takes a JavaScript object as parameter and in defining a javaScript object, var should not be used in the properties.
//This is correct
{
prop: "Something"
}
//This is not
{
var prop: "Something"
}
I have 3 collections :
events :
{
_id: ObjectId(54ca0f2506d0c6b673b2fde8),
_reference: ObjectId("54fd786c549e96f70f9c027d")
},
{
_id: ObjectId(54acd81941a646d768922cfa),
_reference: ObjectId("54fd786c549e96f70f9c027d")
}
posts :
{
_id: ObjectId(54fd786c549e96f70f9c027d),
title: "This is a post",
content: "This is the content of the post"
}
comments :
{
_id: ObjectId(54fd786c549e96f70f9c027e),
content: "This is a comment on a post"
}
When a post or a comment is created, a document is also created in the collection "events" with a property called "_reference". This "_reference" will hold the ObjectId of the comment or post.
Then i need to recover all the documents (saved in the other collections ; i.e posts and comments) thats referenced in each document in the collection "events".
i used the populate method but that only allows me to check in ONE collection when I need to check in ALL the existing collections.
Bellow is an example of how I defined the reference property in the mongoose model :
_reference: {type: Schema.Types.ObjectId, ref: 'posts'}
Thanks in advance !
You cannot define the schema of events like:
_reference: {type: Schema.Types.ObjectId, ref: 'posts'}
and expect it to refer to comments as well. Because you're telling explicitly that the reference is for posts.
A better approach would be to save an ObjectID in events for the object you want to save, add a field called type where you would say if it's a comment or a post, and according to that, look up the designated collection for the ObjectId.