I'm new at this, I need to get all the persons from the db that matches the day of the week of the attribute createdAt (a Date) and a day of the week obtained through a parameter in the request. My data model is:
const personSchema = new mongoose.Schema({
firstName: {
required: true,
type: String
},
lastName: {
required: true,
type: String
},
age: {
required: true,
type: Number
},
email: {
type: String
},
createdAt: {
type: Date,
default: Date.now
}
})
I'm working with MongoDB and Node.js
I've tried this:
const people = await Person.aggregate(
[{
$addFields: {
dayyOfWeek: {
$dayOfWeek: "$createdAt"
}
}
}, {
$match: {
dayyOfWeek: {
$eq: req.params.weekday
}
}
}]
)
and tried too with $where and $function in the find function, but it goes wrong because that gives me an error, "MongoError: $where is not allowed in this atlas tier"
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 } } }
])
I have message document with groupId and createdTS fields.
and for query i have array of objects with groupId and lastVisit.
I want to query all messages per groupId after lastVisit
I tried with $in with groupIds but it is not filtering createdTS with lastVisit
member schema
const GroupMemberSchema = new mongoose.Schema({
userId: { type: String, required: true },
groupId: { type: String, required: true },
addTS: { type: Date, default: Date.now },
lastVisit: { type: Date, default: Date.now }
});
Message Schema
const GroupMessageSchema = new mongoose.Schema({
id: { type: String, required: true },
groupId: { type: String, required: true },
content: { type: String, required: true },
createdTS: { type: Date, default: Date.now },
});
for query
GroupMessage.find({groupId: {$in: groupIds}})
If I understood the question correct then you need to fetch records that match each groupId and at the same time are greater than appropriate lastVisit. If to translate it to MongoDB query it would be something like this:
{
"$or": [
{
"$and": [
{ "groupId": _groupId[i] },
{ "createdTS": { "$gt": _lastVisit[i] } }
]
},
...
]
}
Where _groupId[i] and _lastVisit[i] are array elements for list of groups and lastVisit timestamps.
I'm trying to add a value to a nested schema:
groups = new SimpleSchema({
title: { type: String, optional: true },
element: { type: [elements], optional: true }
});
elements = new SimpleSchema({
description:{ type: String, optional: true },
anything: { type: String, optional: true }
});
MongoDB.attachSchema(new SimpleSchema({
title: { type: String },
slug: { type: String, unique: true },
language: { type: String, defaultValue: "en" },
group: { type: [groups], optional: true },
}));
Now I want to add just a new element-description to an existing entry in the DB. I tried this, but it doesn't work.
Uncaught Error: When the modifier option is true, validation object must have at least one operator
var newElement = {
description: 'insert this as a new element description'
};
MongoDB.update({ _id: Id }, { $push: { 'group.element': newElement }}, function(error) { if(error) console.warn(error); });
Is it correct to use 'group.element' as a $push-parameter?
Update
I forgot the index of group: $push: { 'group.0.element': newElement }
Also I have to define elements before groups in the schema.
I have the following Scheme:
dGroup = new SimpleSchema({
title: { type: String, optional: true },
element: { type: String, optional: true }
});
MongoDB.attachSchema(new SimpleSchema({
title: { type: String },
slug: { type: String, unique: true },
language: { type: String, defaultValue: "en" },
group: { type: [dGroup], optional: true },
}));
... and in the DB I got this:
{ "_id" : "ag9qXWpCYm87kZbEk", "title" : "Test", "slug" : "test", "language" : "en" }
Now I want to add a dGroup -> title:
updates['group.title'] = 'insert this as a new group title with no element';
MongoDB.update({ _id: Id }, { $push: updates }, function(error) { if(error) console.warn(error); });
But this doesn't work. So I need some help to add subdocuments in meteor in case they do not exist.
Try declaring your object first and push it properly, like this:
var newGroup = {
title: 'insert this as a new group title with no element'
};
MongoDB.update({ _id: Id }, { $push: {group: newGroup }}, function(error) { if(error) console.warn(error); });