how to unwind in moongose after populate - mongodb

I have two schemas, Mails and Users, as defined here:
var MailsSchema = new Schema({
from : [{ type: ObjectId, ref: 'UsersSchema' }],
to : [{ type: ObjectId, ref: 'UsersSchema' }],
date : { type: Date, default: Date.now },
subject : { type: String, default: '' },
message : { type: String, default: '' },
isRead : { type: Boolean, default: false }
});
var UsersSchema = new Schema({
username : String,
pass : String,
firstName : String,
lastName : String,
age : Number
});
I want to get list of mail that send to specific user, populate the username in 'from' field,
I tried to do it that way:
mails.find({ to: id }).populate('from', 'username').exec(function (err, docs)...
The problem is:
I'm getting an array in 'from' field, I want to get only the username.
I.e. instead of getting this result:
[{"_id":"53fa2902da480e4c0d315fcd","__v":0,"isRead":false,"message":"SABABA","subject":"MA KORE","date":"2014-08-24T18:03:46.428Z","to":["53f9dbe164b1375c1c5b997a"],"from":[{"_id":"53f9dbe164b1375c1c5b997a","username":"adaroh"}]}]
I want to get that result:
[{"_id":"53fa2902da480e4c0d315fcd","__v":0,"isRead":false,"message":"SABABA","subject":"MA KORE","date":"2014-08-24T18:03:46.428Z","to":["53f9dbe164b1375c1c5b997a"],"from":"adaroh"}]

That's just how populate works. You can modify the docs yourself to filter out the extra id. In your exec, for each doc that gets populated you can look at the from array and do
doc.from[i] = doc.from[i].username

Related

How can I model my MongoDB database to allow me to easily add in new products & user interactions?

I am looking for the best way to model this scenario:
There is a ProductA model. Users can "like" or "dislike" ProductA documents. The documents are then added to an array in the User model called "likes" & "dislikes."
var UserSchema = new mongoose.Schema({
...,
likes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'ProductA' }],
dislikes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'ProductA' }],
...,
});
Now, I have realized that I want to add in a new Product: "ProductB." How do I restructure this database to keep this scalable and allow me to add new products? I am not sure what the best way to do this would be in MongoDB.
I believe my ideal scenario is the following psuedo-model:
var InteractionSchema= new mongoose.Schema({
product: // anonymous reference to an object
productType: //enum of which product it is
user: // user who made the interaction
interactionType: // like or dislike enum
});
I could not find any reference to how to handle anonymous references in MongoDB however. I would appreciate some advice
If I understand your requirement correctly, you can have three collections at a time:
products (contains all the products)
users (contains user information)
user_product_likes (contains user's like/dislike)
Respective schema can be,
UserInformationSchema :
{
name : {
type: String,
required: false
..
},
..
}
ProductSchema :
{
product_type : {
type: Integer,
},
...
}
InteractionSchema :
{
product_id : {
type: Integer
required: true
},
user_id : {
type: Integer
required: true
},
like : {
type: Boolean
required: false,
default:false
},
dislike : {
type: Booelan,
required: false,
default: false
}
}

mongoose: getting unknown objectId when stored string instead of objectId

According to me when i pushed 'ABC' instead of objectId, It should show some error like
Cast to ObjectId failed for value "ABC" at path "likes".
but when i print that updated data i saw some unknown objectId in likes array
My question is, what is that unknown objectId(6a61736f6e20626f75726e65) and why it is generated
automatically
User Model
new Schema({
name: { type: String,required:true},
}, { usePushEach: true ,timestamp:true});
Feed Model
new Schema({
user: { type: Types.ObjectId, ref: 'user', required: true },
name: { type: String,default:null, trim: true },
likes: [{ type : Types.ObjectId, ref: 'user',}],
}, { usePushEach: true ,timestamp:true});
In Feed Schema likes have reference to User Schema
var data = await feed.findByIdAndUpdate(
postId,
{
$push: { likes: 'ABC' }
}
);
if(data){
var data = await feed.findById(postId);
console.log(data.likes);//["6a61736f6e20626f75726e65"]
}
OutPut:
["6a61736f6e20626f75726e65"]
Since you are pushing a String in likes which is not an ObjectId, you are getting this error.
Your schema clearly states that likes is an array of ObjectId:
likes: [{ type : Types.ObjectId, ref: 'user'}],
so you have to pass an ObjectId instead of user's name.
You have to do this:
// Whenever you are pushing value in `likes` `array`,
// you need to get the `ObjectId` of the user who liked the feed.
let userId = <userId_of_Ishwar>;
var data = await feed.findByIdAndUpdate(
postId,
{
$push: { likes: userId }
});

How to give iDs to dynamic fields in React-Redux?

I created a simple dynamic fields in React-Redux with a plus button to add as many field as I want (hobbies) of an already existing form. I'm using mongodb as a database and so I have this error that tells me that my fields/data don't have iDs.
so how can I generate iDs for my data?
this below is my model with featherJs. as you can see this is how I added my hobbies array in the existing model called myService. I can see that my hobbies are created in mongo (using Robo 3T) which is great but i'm having difficulty reusing them (hobbies) in an other component in Redux. I'm not sure if I should give IDs to this fields or create a new service just for them. I never coded something in backend so I'm confused. what's the rule for this kind of situations.
Any other suggestions would be helpful.
warning in Redux: Each child in a list should have a unique "key" prop.
error in api : Cast to ObjectId failed for value at path "_id" for model "
const { Schema } = mongooseClient;
const myService = new Schema({
type: { type: String, enum: VALID_TYPES, required: true },
user: {
type: mongooseClient.Schema.Types.ObjectId,
ref: 'user',
required: true
},
comment: String,
hobbies: [{
type: mongooseClient.Schema.Types.ObjectId,
ref: 'hobbies',
default: [],
required: false }],
date: {
begin: { type: Date, default: Date.now },
current: { type: Date, default: Date.now },
end: { type: Date, required: true },
},
}, {
timestamps: true
});
return mongooseClient.model('myService', myService);
};

How can I add a unique auto increment ID inside mongoDB object

I have a table users. This is the schema.
var usersSchema = mongoose.Schema({
uname : {type : String , unique: true},
email : {type : String},
logintype : {type : String},
password : String,
status : String,
hash : String,
social: {},
games: Object,
os: String,
friends: Object,
msges:Object
});
The msges are objects. But what I want is to have key value pair inside msges. So what I did was
function sendMsgToFriend(uname,friendUname,title,msg,time,callback){
global.users.find({"uname":friendUname},
function(err,doc){
if(err){
callback(false,err,"Msg cannot be sent");
}else{
global.users.update( {"uname" : uname},
{
$addToSet : {
"msges":{time:{"from":uname,"title":title,"msg":msg,"read":false}}
}
},function(err,doc){
if(err){
callback(false,err,"Msg cannot be sent");
}else{
callback(true,null,"Msg has been sent");
}
}
);
}
}
);
}
I tried to make 'time' the key and rest its value. But what happened was that instead of value of time, string "time" appeared. Can I make an auto increment Key of msges? Thankyou in advance.
You define "msgs" as a object but what i read from your question is you want a array of objects..
Why don't you create a model for messages and make make "msgs" an array of references to that object.
var usersSchema = mongoose.Schema({
uname : {type : String , unique: true},
email : {type : String},
logintype : {type : String},
password : String,
status : String,
hash : String,
social: {},
games: Object,
os: String,
friends: Object,
msges: [{
message_id : { type: Schema.Types.ObjectId, ref: 'Message' },
read_on : Boolean }]
});
and a schema for the messages
var messageSchema = Schema({
from : String,
title: String,
msg : String,
send_on : Date
});
var Message = mongoose.model('Message', messageSchema);
This way all messages are in a collection and you can track the read status per user.
For retrieving the messages during user retriaval you can use mongoose populate
UPDATE:
if you don't want an xtra collection make your user schema something like:
var usersSchema = mongoose.Schema({
uname : {type : String , unique: true},
email : {type : String},
logintype : {type : String},
password : String,
status : String,
hash : String,
social: {},
games: Object,
os: String,
friends: Object,
msges: [{
id : Schema.Types.ObjectId,
from : String,
title: String,
msg : String,
send_on : Date,
read_on : Boolean }]
});
But keep in mind that if you also want the message to be present with the user who sended it you need to put it in the array by both users (keep id equal).... So you should think / talk about the best solution in your scenario.

Moongose - how to customize a field in a scheme ? string and array in the same field

I would like to know how I can customize a field where you can use an array and string
eg:
var PostingSchema = new Schema({
created: {
type: Date,
default: Date.now
},
title: {
type: String,
required: true,
trim: true
},
images: Array,
categorie: Array,
ubication:[{ type: Number, ref: 'Place'}],
agg:[{
agg :{ type: String, ref: 'Agg' },
value : String,
make :[{ type: Number, ref: 'Make'}]
}]
});
In the field agg value, I have a problem that can sometimes be of type string and sometimes can be of type array , should be of the array type I populate it with another scheme. How can I do that?
I made a field called "value ->string" and a "make->array" to do if there is a better way?