Mongo nested fields populating issue - javascript

var buyerSchema = new Schema({
cart: [{
id: {
type: Schema.Types.ObjectId,
ref: "product"
},
number: Number
}],
personName: { type: String, required: true, trim: true },
image: { type: String, required: false, trim: true },
email: { type: String, required: true, trim: true }
})
How can i populate the Id field
buyerMdl.findByToken(buyer['token']).populate({path: 'cart', populate: {path : 'id', model : 'product'}})
this particular command is not working for me

First of all make sure your findByToken method returns an instance of find so that you can use .populate() in the chain.
The problem is that you're trying to populate a property which is not referenced. So instead of populating card and then ids in it, you should directly populate cart.ids.
This should work:
buyerMdl
.findByToken(buyer['token'])
.populate({
path: 'cart.id',
model: 'product'
});

Your id is inside card array... So you should use with dot notation to populate id
buyerMdl.findByToken(buyer['token']).populate({ path: 'cart.id' })

Related

CastError: Cast to ObjectId failed for value "{ '$in': [ new ObjectId("6359f421fd4678e2eba3ffee") ] }" (type Object) at path "author" for model "Blog"

I have a blog model:
let blogSchema = new mongoose.Schema({
author: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
title: { type: String, required: true, unique: true },
description: { type: String, required: true, unique: true },
content: { type: String, required: true, unique: true },
likes: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
views: { type: Number, default: 0, required: true },
tags: [],
currentState: { type: String, enum: ['draft', 'published'], required: true, default: 'draft' }}, { timestamps: true });
and a user model which I don't think is necessary to show.
When I try querying for a blog with the author matching a list of userids that the current user is following as such:
let blogs = await Blog.find({ author: { $in: blogIds } })
It gives me the error: CastError: Cast to ObjectId failed for value "{ '$in': [ new ObjectId("6359f421fd4678e2eba3ffee") ] }" (type Object) at path "author" for model "Blog"
How do I get the blogs? I've tried using the $or operator but I would have to loop and it doesn't work anyway. The array values in $in is found correctly as shown in the error, it isn't converting properly though.
The blogids array is [ new ObjectId("6359f421fd4678e2eba3ffee") ]. It is dynamic and is an array of userids that the user follows (OOPS, the name isn't clear)
I think there might be problem in your blogIds array.Try to convert all value inside it with mongoose.Types.ObjectId.
const allIds=blogIds.map(item=>mongoose.Types.ObjectId(item));
Then update your find query.
const blogs = await Blog.find({ author: { $in: allIds } });

How to implement a deep populate using the Mongoose, to properly output a M:N database relation?

I am trying to create a basic social media website, with post having different comments, likes, comments also having likes. If the logged in user is the one that made the comment or post, he could be able to delete the post.
So I have to use the deep populate method of mongoose, but the issue I am having is, when the content of the comment is showing, then the name of the user that made that comment is missing.
Post Schema is as follows
content: {
type: String,
required: true
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
// include the array of ids of all comments in this post schema itself
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}
],
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Like'
}
]
},{
timestamps: true
});
Like Schema is as follows -
const likeSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.ObjectId
},
// this defines the object id of the liked object
likeable: {
type: mongoose.Schema.ObjectId,
require: true,
refPath: 'onModel'
},
// this field is used for defining the type of the liked object since this is a dynamic reference
onModel: {
type: String,
required: true,
enum: ['Post', 'Comment']
}
}, {
timestamps: true
});
User Schema is as follows -
const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
name: {
type: String,
required: true
},
avatar: {
type: String
}
}, {
timestamps: true
});
Comment Schema is as follows -
const commentSchema = new mongoose.Schema({
content: {
type: String,
required: true
},
// comment belongs to a user
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
post: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
},
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Like'
}
]
},{
timestamps: true
});
And this is the populate function, on the front end I am trying to display all possible posts with all possible likes and comments, with all the comments also having likes. And obviously the name of the user that made the comment -
let posts = await Post.find({})
.sort('-createdAt')
.populate('user')
.populate({
path: 'comments',
populate: {
path: 'user'
},
populate: {
path: 'likes'
}
}).populate('comments')
.populate('likes');
But in the front end, I am not able to display the User Name that made a particular comment.
Please tell the error.

passing nested JSON data from mongoose model is not working

I am pushing nested JSON data to database. This is how my schema looks like,
const mongoose = require('mongoose');
// original Schema
const dataSourceSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true, unique: true },
type: { type: String, required: true },
projectId: { type: mongoose.Schema.Types.ObjectId, ref: 'Project', required: true },
config:{type: String, required: true}
});
module.exports = mongoose.model('DataSource', dataSourceSchema);
I would like to pass the following json data to my dataSourceSchema,
{
“name”:”JdbcSourceConnector”,
"type" :"string",
“config”: {
“connector.class”:” io.confluent.connect.jdbc.JdbcSourceConnector”,
“tasks.max”:1,
“connection.url”:”<connection to connect to database along with username and password>”,
“mode”:”incrementing”,
“incrementing.column.name”:”<incrementing column name in table>”,
“topic.prefix”:”test-mysql-jdbc-”
}
}
But its not taking, gives casting error or ',' expected.
So i tried this,
const dataSourceSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true, unique: true },
type: { type: String, required: true },
projectId: { type: mongoose.Schema.Types.ObjectId, ref: 'Project', required: true },
config:{
connector.class:{ type: String, required: true },
tasks.max:{ type: String, required: true },
connection.url:{ type: String, required: true },
mode:{ type: String, required: true },
incrementing.column.name:{ type: String, required: true },
topic.prefix:{ type: String, required: true }
}
});
this Schema is also giving me errors, ',' expected.
If i pass just a string as i have mentioned in my original schema, the data gets stored in db.
but i want to pass the nested json data, please guide me in right direction.
I also tried stringify the data , its not working.
As I see it , the error lies in defining you schema with your second schema you came close to the answer. Change you schema as follows:
const dataSourceSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true, unique: true },
type: { type: String, required: true },
projectId: { type: mongoose.Schema.Types.ObjectId, ref: 'Project', required: true },
config:{
connectorClass:{ type: String, required: true },
tasksMax:{ type: String, required: true },
connectionUrl:{ type: String, required: true },
mode:{ type: String, required: true },
incrementingColumnName:{ type: String, required: true },
topicPrefix:{ type: String, required: true }
}
});
I have suggested the change as mongoose doesn't understand the dot notation in the key column of it's schema, hence you were receiving the error you have mentioned.
If you want to use the dot notation for some reason encapsulate the key in " and not in the special character as appearing in your code snippet.
P.s. - Don't forget to change the key names in your json

Unique field for unique id [duplicate]

I have a special case where our collection needs to make sure each document is unique based on a combination of the email address, and the sweepstakes_id. I've looked all over, but I can't find how to accomplish this type of validation.
Schema definition:
var submissionSchema = new Schema({
client_id: {
type: Schema.Types.ObjectId,
ref: 'Client',
index: true
},
sweepstakes_id: {
type: Schema.Types.ObjectId,
ref: 'Sweepstakes',
index: true
},
email: {
type: String,
index: true
},
data: {
type: Schema.Types.Mixed,
default: []
}
});
You can enforce that using a unique index that includes both fields:
submissionSchema.index({ email: 1, sweepstakes_id: 1 }, { unique: true });

Returning specific fields with mongoose

I'm trying to accomplish something really easy but still manage to fail.
What I am trying to do is when I get a get request on my server I want to return all documents BUT just the specific fields populated.
My schema goes as follows
var clientSchema = new Schema({
name:{
type: String,
required: true
},
phone:{
type: String,
required: true
},
email:{
type: String,
required: true
},
address: {
type: String,
required: false
}
});
var orderDetailsSchema = new Schema({
//isn't added to frontend
confirmed:{
type: Boolean,
required: true,
default: false
},
service:{
type: String,
required: true
},
delivery:{
type: String,
required: false
},
payment:{
type: String,
required: false
},
status:{
type: String,
required: true,
default: "new order"
},
});
var orderSchema = new Schema({
reference:{
type: String,
required: true
},
orderdetails: orderDetailsSchema,
client: clientSchema,
wheelspec: [wheelSchema],
invoice:{
type: Schema.Types.ObjectId,
ref: 'Invoice'
}
});
What I want is to return only client.phone and client.email plus orderdetails.status but still retain reference field if possible
I have tried using lean() and populate() but had no luck with them. Is there anything utterly simple I am missing? Or what I am trying to achieve is not that easy?
Thanks!
You can specify the fields to return like this:
Order.findOne({'_id' : id})
.select('client.phone client.email orderdetails.status reference')
.exec(function(err, order) {
//
});
Alternative syntax
Order.findOne({'_id' : id})
.select('client.phone client.email orderdetails.status reference')
.exec(function(err, order) {
//
});
I've made a number of assumptions here, but you should be able to see the idea.
Simply do like this :-
Order is model name which is registered in mongoose.
Order.findById(id) // set id you have to get
. populate('client')
.select('client.phone client.email orderdetails.status reference')
.exec(function(err, order) {
//
});
You can use projection.
await Order.findById(diaryId, {phone: 1, email: 1, status: 1})
If phone:1 is set to 1, it is included, if phone:0, then it's excluded.

Categories