javascript extend an object not working - javascript

Banging my head against the wall and I know it's gotta be something stupid...
I have a basic comment(review)/voting system. I am pulling the reviews from the mongo db and in an asysnc.waterfall function, trying to add the votes to each review. Here is the function that adds the votes:
function(reviews, callback) {
let newReviews = [];
_.forEach(reviews, function(review,idx) {
Vote.find({review:review._id}).exec(function(err1, votes){
if (err1){
callback(err1,null);
}else{
console.log("1: REVIEW - ", review);
review.votes = votes;
console.log("2: VOTES - ", review.votes);
newReviews.push(review);
console.log("3: REVIEW - ", review);
if( newReviews.length == reviews.length ){
callback(null,newReviews);
}
}
});
});
}
The votes item never gets populated even though there's data there. Here's some output from those logging statements:
1: REVIEW - { _id: 5a2086139c3c077e546622,
user:
{ passProfileImageURL: '/modules/users/client/img/profile/default.png',
_id: 5a15cd47b9fd942e50e5b,
provider: 'local',
username: 'xxx',
profileImageURL: '/modules/users/client/img/profile/default.png' },
beach:
{ _id: 57995db6666f1ec6f3750,
slug: 'carmel-city-beach-carmel-by-the-sea-california-united-states',
Name: 'Carmel City Beach' },
totalVotes: 1,
reports:
[ { _id: 5a2087f672107f48dd4ed,
user: 5a15cd47db50942e50e5b,
review: 5a208639c3c077e546622,
__v: 0,
updated: 2017-11-30T22:36:38.598Z,
created: 2017-11-30T22:36:38.598Z } ],
created: 2017-11-30T22:30:14.276Z,
comment: 'Why am i doing this???',
rating: 3 }
2: VOTES - [ { _id: 5a26fab26a6f85b39484,
review: 5a20867c3c077e546622,
Type: 'review',
user: 5a15cd4db50942e50e5b,
__v: 0,
updated: 2017-12-05T19:59:46.318Z,
created: 2017-12-05T19:59:46.318Z,
IsVote: true } ]
3: REVIEW - { _id: 5a208676139c3c077e546622,
user:
{ passProfileImageURL: '/modules/users/client/img/profile/default.png',
_id: 5a15cd47b50942e50e5b,
provider: 'local',
username: 'mit',
profileImageURL: '/modules/users/client/img/profile/default.png' },
beach:
{ _id: 579db6666fcec6f3750,
slug: 'carmel-city',
Name: 'Carmel City' },
totalVotes: 1,
reports:
[ { _id: 5a2087b107f48dd4ed,
user: 5a15cfdb50942e50e5b,
review: 5a208673c077e546622,
__v: 0,
updated: 2017-11-30T22:36:38.598Z,
created: 2017-11-30T22:36:38.598Z } ],
created: 2017-11-30T22:30:14.276Z,
comment: 'Why am i doing this???',
rating: 3 }
Doesn't make sense that the number 2 item would log correctly, but 3 does not...can anyone help me make sense of this stupid issue? Or is it just me? LOL
As requested, here's the Vote mongoose schema definition:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var config = {
Type: {
type: String
},
IsVote: {
type: Boolean,
default: true
},
created: {
type: Date,
default: Date.now
},
updated: {
type: Date,
default: Date.now
},
owner: {
type: Schema.ObjectId
},
user: {
type: Schema.ObjectId,
ref: 'User'
},
review: {
type: Schema.ObjectId,
ref: 'Review'
}
};
var VoteSchema = new Schema(config, {
collection: 'votes'
});
/**
* Hook a pre save method to hash the password
*/
VoteSchema.pre('save', function(next) {
next();
});
VoteSchema.method('toggleVote', function() {
this.IsVote = !this.IsVote;
return this.save();
});
VoteSchema.static('createFromReview', function(reviewId, user) {
return new this({
review: reviewId,
Type: 'review',
user: user
});
});
mongoose.model('Vote', VoteSchema);

Related

Failed to delete the a comment on post?

I'm trying to delete a comment on a post, but I'm unable to find the comment. When I'm console.log(post.comments) it shows me all the comments but still, I can't find the comment. The error was Comment not found which I wrote to find that comment is still there or not. But the comment was there I matched the id with it. Help me I'm new to NodeJs. Help me to fix this
*As a frontend I'm using react and redux I think the problem is in the backend, I've also tested with the postman. Can't delete the comment from postman.
here is the comment route and controller
router.route('/:id/comment/:comment_id').delete(protect, deleteComment);
export const deleteComment = asyncHandler(async (req, res) => {
const post = await Post.findById(req.params.id);
const comment = post.comments.find(
(comment) => comment._id === req.params.comment_id
);
if (!comment) {
res.status(404);
throw new Error('Comment not found');
}
//Check User
if (comment.user.toString() === req.user._id.toString()) {
post.comments = post.comments.filter(
({ id }) => id !== req.params.comment_id
);
await post.save();
return res.json(post.comments);
} else {
res.status(401);
throw new Error('User not authorized');
}
});
here is the post model
import mongoose from 'mongoose';
const postSchema = mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: [true, 'Please Author is required'],
},
title: {
type: String,
required: true,
},
desc: {
type: String,
required: true,
},
img: {
type: String,
},
isLiked: {
type: Boolean,
default: false,
},
isDisLiked: {
type: Boolean,
default: false,
},
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
],
disLikes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
],
comments: [
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
text: {
type: String,
required: true,
},
name: {
type: String,
},
pic: {
type: String,
},
date: {
type: Date,
default: Date.now,
},
},
],
categories: {
type: Array,
},
},
{
timestamps: { createdAt: 'created_at', updatedAt: 'modified_at' },
}
);
const Post = mongoose.model('Post', postSchema);
export default Post;
When you access to the _id you are accessing the instance of the ObjectId
You should try to compare with the id, that is a string representation of the _id
const comment = post.comments.find(
(comment) => comment.id === req.params.comment_id
);

Mongoose like SQL Distinct with latest date

I try to find all data in my collection with mongoose but I have some problems to understand.
Now I use
const mongoose = require('mongoose');
const CaseSchema = new mongoose.Schema({
szenario: {
type: String,
default: 'deprecated'
},
name: {
type: String,
default: 'test'
},
date: {
type: Date,
default: Date.now
}
});
const Case = mongoose.model('tests', CaseSchema);
module.exports = Case;
May idea of the call is:
Case.find().distinct(name).exec();
But how I can select it distinct for the newest date with mongoose?
To get distinct name with lastest date, you need perform MongoDB aggregation with $group operator:
Case.aggregate([
{
$sort: {
name: 1,
date: 1
}
},
{
$group: {
_id: "$name",
data: {
$last: {
date: "$date",
_id: "$_id"
}
}
}
},
{
$project: {
_id: "$data._id",
date: "$data.date",
name: "$_id"
}
}
]).exec((err, cases) => {
if (err) throw err;
console.log(cases);
});
MongoPlayground

Can't compare moment dates in MongoDb

So my goal is to retrieve posts with comments that are placed today with Mongoose.
First, I create a start-of-the-day UTC current date object with:
const todayForEvent = moment().startOf('day')
.utc().toDate();
this results in 2019-01-02T06:00:00.000Z
then I want to create a DB search with mongoose to fetch the posts where a comment has been placed today
const posts = await Post.find({
// From this user...
$and: [
// Find normal posts that has comments (recent interactions)
{ _posted_by: userId },
{ comments: { $exists: true, $ne: [] } },
{ 'comments.created_date': { $gte: todayForEvent } }
]
})
Third, I have mongoose comment documents that have a property created_date
const CommentSchema = new Schema({
created_date: {
type: Date,
default: moment().utc().toDate()
}
});
const Comment = mongoose.model('Comment', CommentSchema);
module.exports = Comment;
This is the result document after placing a comment
Everything looks OK but for some reason the posts array is still empty after the database search, can someone please tell me what I did wrong
EDIT: added post schema at request
const mongoose = require('mongoose');
const { Schema } = mongoose;
const PostSchema = new Schema({
content: {
type: String,
trim: true
},
_content_mentions: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
type: {
type: String,
required: true,
enum: ['normal', 'event', 'task']
},
_liked_by: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
comments_count: {
type: Number,
default: 0
},
comments: [{
type: Schema.Types.ObjectId,
ref: 'Comment'
}],
_group: {
type: Schema.Types.ObjectId,
ref: 'Group',
required: true
},
_posted_by: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
task: {
due_to: {
type: String,
default: null
},
_assigned_to: {
type: Schema.Types.ObjectId,
ref: 'User'
},
status: {
type: String,
enum: ['to do', 'in progress', 'done']
}
},
event: {
due_to: {
type: Date,
default: null
},
_assigned_to: [{
type: Schema.Types.ObjectId,
ref: 'User'
}]
},
created_date: {
type: Date,
default: Date.now
},
files: [{
orignal_name: {
type: String,
default: null
},
modified_name: {
type: String,
default: null
}
}]
});
const Post = mongoose.model('Post', PostSchema);
module.exports = Post;
EDIT 2: sample post document
{ _id: 5c2d14c30176ac30204809a8,
task: { due_to: null },
event: { due_to: null, _assigned_to: [] },
_content_mentions: [],
_liked_by: [],
comments_count: 1,
comments: [ 5c2d14dc0176ac30204809ab ],
content: '<p>poging 5 duust</p>',
type: 'normal',
_posted_by:
{ _id: 5c292e0e63deb43d9434f664,
profile_pic: 'default_user.png',
first_name: 'Jaspet',
last_name: 'Houthoofd' },
_group: 5c292db763deb43d9434f660,
created_date: 2019-01-02T19:45:07.710Z,
files: [],
__v: 0,
liked_by: [] }
**EDIT 3: sample comment **
{ _content_mentions: [],
created_date: 2019-01-02T21:10:04.456Z,
_id: 5c2d28c251f2bd332cdeaf0a,
content: '<p>hehe</p>',
_commented_by: 5c292db763deb43d9434f65f,
_post: 5c2d1dd254ca0429b470f000,
__v: 0 }
So the problem here is that you have two collections, posts and comments. Based on your Posts schema, comments array contains only ids that reference documents that are stored in second collection. That's why you can check whether that array exists and is not empty but you can't refer directly to these elements.
To fix that you can use $lookup to get those documents from comments into posts and then you can apply your date condition inside $match, try:
let posts = await Post.aggregate([
{ $match: { comments: { $exists: true, $ne: [] }, _postedBy: userId } },
{ $lookup: { from: "comments", localField: "comments", foreignField: "_id", as: "comments" } },
{ $match: { 'comments.created_date': { $gte: todayForEvent } } }
])

Mongoose combine two queries for same collection

I am trying to make a query to find documents depending on another document in the same collection as below.
The first one finds the user and the second one finds the data by using that user data received. But I want to do it with one query like join in SQL
This is schema
var ConnectionSchema = new Schema({
socketId: {
type: String,
require: true
},
location: {
type: [Number],
index: '2dsphere'
},
user: { type: Schema.ObjectId, ref: "User" },
date: {
type: Date,
require: true,
default: new Date()
}
});
// queries
return mongoose.model("Connection").findOne({ user: userId }).populate("user").then(usr => {
return mongoose.model("Connection").find({
location: {
$near: {
$maxDistance: config.searchDistance,
$geometry: { type: Number, coordinates: usr.location }
}
},
user: { $ne: userId },
});
});
Is there any way to do that with a just single query?
Thanks.
yes there is a way you can do like this
return mongoose.model("Connection").findOne({ user: userId })
.populate("user" ,
match : {$and : [{location: {
$near: {
$maxDistance: config.searchDistance,
$geometry: { type: Number, coordinates: usr.location }
}
}},
{user: { $ne: userId }}]})
.then(usr => {
// perform your action
});

JavaScript object element is missing during Mongoose update query

I'm trying to update a new field of data into an existed document, but some of the data is not updating.
In my AngularJS controller:
$scope.tellUsMore = function(){
var data = {
businessPhone:$scope.usersData.phone,
businessEmail:$scope.usersData.email,
businessFb:$scope.usersData.fb,
businessTwitter:$scope.usersData.twitter,
businessInstagram:$scope.usersData.instagram,
businessAboutUs:$scope.usersData.aboutUs,
businessTags:$scope.tags,
businessFeatures:$scope.features,
businessLocation:$scope.usersData.location,
businessPriceRange:$scope.usersData.priceRange,
businessPreparationTimeRange:$scope.usersData.preparationTimeRange
}
console.log(data); //result below
Account.updateProfile(data)
.success(function() {
alert("DONE")
})
.error(function(error) {
console.log(error)
});
}
the console.log(data) result on chrome console tab
Object
businessAboutUs: "LOL"
businessEmail: "example#gmail.com"
businessFb: undefined
businessFeatures: Array[5]
businessInstagram: undefined
businessLocation: Object
businessPhone: "0123456789"
businessPreparationTimeRange: 2
businessPriceRange: 2
businessTags: Array[2]
businessTwitter: undefined
__proto__: Object
In my Node.js server
this.updateProfile = function(req, res, next){
var data = req.body;
console.log(data)//result below
User.update(req.user, {$set: { businessDetails:data }}, {upsert: true}, function(err,user){
res.status(200);
});
}
the console.log(data) result in my terminal
{ businessPhone: '0123456789',
businessEmail: 'example#gmail.com',
businessAboutUs: 'LOL',
businessTags:
[ { name: 'Marina Augustine',
email: 'm.augustine#exampleas.com',
image: 'http://lorempixel.com/50/50/people?0',
_lowername: 'marina augustine' },
{ name: 'Oddr Sarno',
email: 'o.sarno#exampleas.com',
image: 'http://lorempixel.com/50/50/people?1',
_lowername: 'oddr sarno' } ],
businessFeatures:
[ { id: 1, title: 'Do you accept credit card ?', selected: true },
{ id: 2,
title: 'Do you accept table reservation ?',
selected: false },
{ id: 3,
title: 'Do you provide Wi-Fi for your customer ?',
selected: false },
{ id: 4, title: 'Is your product Halal ?', selected: true },
{ id: 5,
title: 'Do you provide parking for your customer ?',
selected: true } ],
businessLocation: { latitude: 3.1168450143582223, longitude: 101.60914228515628 },
businessPriceRange: 2,
businessPreparationTimeRange: 2 }
However, this is what I got – only businessLocation updated to businessDetails, and the businessLocation is not even complete.
> db.users.find().pretty()
{
"_id" : ObjectId("554eb9a8bfa096290c9efa46"),
"companyName" : "t and co",
"email" : "example#gmail.com",
"password" : "$2a$10$79b.XztwEXgdCPDxTkg4ieICSkYyKw4uXG/2E0WShSZxXVdGdwObm",
"dateJoined" : ISODate("2015-05-10T01:51:36.120Z"),
"accountVerified" : false,
"locationVerified" : false,
"__v" : 0,
"businessDetails" : {
"businessLocation" : {
}
}
}
>
schema for user
var userSchema = new db.Schema({
email: { type: String, unique: true, lowercase: true },
password: { type: String, select: false },
companyName: String,
locationVerified: { type:Boolean, default:false},
accountVerified: { type:Boolean, default:false},
dateJoined: {type:Date, default:Date.now}
})
value of req.user
554eb9a8bfa096290c9efa46 this is an objectID in mongodb
You need to define the businessDetails subdoc in userSchema if you want to be able to update it:
var userSchema = new db.Schema({
email: { type: String, unique: true, lowercase: true },
password: { type: String, select: false },
companyName: String,
locationVerified: { type:Boolean, default:false},
accountVerified: { type:Boolean, default:false},
dateJoined: {type:Date, default:Date.now},
businessDetails: {
businessPhone: String,
businessEmail: String,
businessAboutUs: String,
businessTags: [],
businessFeatures: [],
businessLocation: {
latitude: Number,
longitude: Number
},
businessPriceRange: Number,
businessPreparationTimeRange: Number
}
})

Categories