Query sub documents in mongoose - node.js

I am new to node.js.
I am having JSON object of the form
{ "_id" : ObjectId("540b03ddf1768fe562fbb715"),
"productid" : "men1",
"comments" : [ { "name" : "shiva", "text" : "Haidddsdcccccc", "_id" : ObjectId("540b03dd0570a6261e20a59e"), "date_entered" : ISODate("2014-09-06T12:53:49.658Z") },
{ "name" : "shiva", "text" : "Haidddsdcccccc", "_id" : ObjectId("540cb2be35f8145a2d296ea0"), "date_entered" : ISODate("2014-09-07T19:32:14.827Z") },
{ "name" : "shiva", "text" : "Haidddsdcccccc", "_id" : ObjectId("540cb2c335f8145a2d296ea1"), "date_entered" : ISODate("2014-09-07T19:32:19.456Z") } ] }
I want to query comments of a product after a specific time
I am using query as
var query=Product.find({"productid":obj.productid,
'comments.date_entered': {$gt: obj.timed}}, {'comments.$': 1})
I am getting only one object after the specific time i.e
{
_id: "540b03ddf1768fe562fbb715"
comments: [1]
0: {
name: "shiva"
text: "Haidddsdcccccc"
_id: "540cb2be35f8145a2d296ea0"
date_entered: "2014-09-07T19:32:14.827Z"
}
}
How to get all the comments of the product after the specified time?

Doesn't seem to be a good way to do this from what I can find out. A work-around could be doing something like this:
Product.findOne({productid: PRODUCT_ID}, {comments: 1}, function(err, product) {
var comments = product.comments.filter(function(comment) {
return comment.date_entered > DATE;
});
...
})

Related

How to fetch document with filtered nested document using Mongo query?

Here is my organization collection.
[{
"_id" : ObjectId("5fd5fc1b9f117029b5233b2e"),
"name" : "ClassA",
"orgMembers" : [
{
"_id" : ObjectId("5fd5fc1b9f117029b5233b2f"),
"userId" : "Ben",
},
{
"_id" : ObjectId("5fd5fc1b9f117029b5233b2f"),
"userId" : "Anton",
}
],
},
{
"_id" : ObjectId("5fd5fc1b9f117029b5233b2e"),
"name" : "ClassA",
"orgMembers" : [
{
"_id" : ObjectId("5fd5fc1b9f117029b5233b2f"),
"userId" : "Ben",
}
],
}]
Each document has properties like _id, name, orgMembers which represent document information.
And orgMembers is the Array of Members (_id, userId) who belongs to organization.
In this collection, I want to fetch the organizations which includes orgMember with Anton as userId and as well orgMembers of fetched organization document should only contain Anton as a orgMember.
Expected Result is likewise
[{
"_id" : ObjectId("5fd5fc1b9f117029b5233b2e"),
"name" : "ClassA",
"orgMembers" : [
{
"_id" : ObjectId("5fd5fc1b9f117029b5233b2f"),
"userId" : "Anton",
}
],
}]
Here ClassA organization has two orgMembers but need to be filtered matching with userId.
I have tried with
documentModel.find({ 'orgMembers.userId': 'Anton' })
But within this query, I get the result like this.
[{
"_id" : ObjectId("5fd5fc1b9f117029b5233b2e"),
"name" : "ClassA",
"orgMembers" : [
// should be omitted
{
"_id" : ObjectId("5fd5fc1b9f117029b5233b2f"),
"userId" : "Ben",
},
// should be contained
{
"_id" : ObjectId("5fd5fc1b9f117029b5233b2f"),
"userId" : "Anton",
}
],
}]
For expected result, orgMember with userId: Ben should be omitted.
How can I get my expected result with mongo query?
I believe this will be worked on your side
db.collection.find({
"orgMembers.userId": "Anton"
},
{
orgMembers: {
"$elemMatch": {
userId: "Anton"
}
}
})
not sure if i quite got your requirement:
but try this if it works
db.collection.find({
"orgMembers.userId": {
$regex: "Anton",
$options: "i"
}
},
{
name: 1,
"orgMembers.$": 1
})
this is to return only the userId you are looking for in orgMembers.if there are more orgmembers they will not be part of output

How to delete an nested object based on its ObjectId?

I have this nested Schema for my courses collections, there is a sessions array in every course and a students array in every session and every student is an object consisting of a property of userName with a value of ObjectId refering to my users collections and another property names status containing some number.
I want to delete an student object from my students array of my session with its _id.
I know it is possible to unwind arrray to get to a single object but I need a neat way like using an objectId to delete an object from database so that we don't have to specify path like directly deleting or modifying that nested subdocument.
This is my course schema:
CourseSchema = new mongoose.Schema({
name:String,
sessions:[
{
date:Date,
students :[{
userName:{
type:mongoose.Schema.Types.ObjectId,
ref :'users'
},
status:Number
}]
}
]
})
You can use the following DELETE route to delete a student from a course session.
router.delete(
"/course/:courseId/session/:sessionId/student/:studentId",
async (req, res) => {
try {
let result = await Course.updateOne(
{ _id: req.params.courseId, "sessions._id": req.params.sessionId },
{
$pull: { "sessions.$.students": { userName: req.params.studentId } }
}
);
res.send(result);
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong");
}
}
);
Let's say you have a course like this:
{
"_id" : ObjectId("5de907acdfcef9493cd215a8"),
"name" : "Course 1",
"sessions" : [
{
"date" : ISODate("2019-12-05T16:32:41.998+03:00"),
"_id" : ObjectId("5de907acdfcef9493cd215a9"),
"students" : [
{
"_id" : ObjectId("5de907acdfcef9493cd215ac"),
"userName" : ObjectId("5de8e4c8f74cf254d04f90d8"),
"status" : 1
},
{
"_id" : ObjectId("5de907acdfcef9493cd215ab"),
"userName" : ObjectId("5de8e4d5f74cf254d04f90d9"),
"status" : 1
},
{
"_id" : ObjectId("5de907acdfcef9493cd215aa"),
"userName" : ObjectId("5de8e4ddf74cf254d04f90da"),
"status" : 1
}
]
}
],
"__v" : 0
}
If we want to delete the student with userName with value 5de8e4ddf74cf254d04f90da, we can send a DELETE request to our route using an url like this:
http://localhost/courses/5de907acdfcef9493cd215a8/session/5de907acdfcef9493cd215a9/student/5de8e4ddf74cf254d04f90da
5de907acdfcef9493cd215a8--> courseId
5de907acdfcef9493cd215a9--> sessionId
The response will be like this:
{
"n": 1,
"nModified": 1,
"ok": 1
}
When we look at our course, we see the student is removed:
{
"_id" : ObjectId("5de907acdfcef9493cd215a8"),
"name" : "Course 1",
"sessions" : [
{
"date" : ISODate("2019-12-05T16:32:41.998+03:00"),
"_id" : ObjectId("5de907acdfcef9493cd215a9"),
"students" : [
{
"_id" : ObjectId("5de907acdfcef9493cd215ac"),
"userName" : ObjectId("5de8e4c8f74cf254d04f90d8"),
"status" : 1
},
{
"_id" : ObjectId("5de907acdfcef9493cd215ab"),
"userName" : ObjectId("5de8e4d5f74cf254d04f90d9"),
"status" : 1
}
]
}
],
"__v" : 0
}
As we see the student with username with value 5de8e4ddf74cf254d04f90da does not exists anymore in the course session, meaning it is removed.

Mongoose array of objects query by slug

I am trying to make a query for documents that have an array of objects like this. its a history of when a tag was added.
{
"added_by" : ObjectId("58d92d8b11af264b87a8f5d4"),
"tag" : ObjectId("58d92d8b11af264b87a8f5ed"),
"_id" : ObjectId("58d92d8c11af264b87a8f6d5"),
"added_at" : ISODate("2017-03-02T22:06:42.788Z")
}
I am not able to make the query on the slug just the _id
I have tried this:
var query = {
'tags.tag': {
slug: $in: ['tag-name']
}
}
Node.find(query, (err, nodes) => {
if (err) {
res.status(404)
res.send(err)
} else {
res.json(nodes);
}
}).populate(['tags.tag'])
Here is the document:
{
"_id" : ObjectId("58d92d8c11af264b87a8f6d0"),
"user_id" : ObjectId("58d92d8b11af264b87a8f5d4"),
"uid" : "-KeG2FvL0jwkHFvOautH",
"updated_at" : ISODate("2017-03-02T22:06:42.788Z"),
"created_at" : ISODate("2017-03-02T22:06:42.051Z"),
"tags" : [
{
"added_by" : ObjectId("58d92d8b11af264b87a8f5d4"),
"tag" : ObjectId("58d92d8b11af264b87a8f5ed"),
"_id" : ObjectId("58d92d8c11af264b87a8f6d5"),
"added_at" : ISODate("2017-03-02T22:06:42.788Z")
},
{
"added_by" : ObjectId("58d92d8b11af264b87a8f5d4"),
"tag" : ObjectId("58d92d8b11af264b87a8f626"),
"_id" : ObjectId("58d92d8c11af264b87a8f6d4"),
"added_at" : ISODate("2017-03-02T22:06:42.788Z")
}
],
"status" : "publish",
"description" : "some text here",
"title" : "Anna James",
"__v" : 0
}
Any thoughts?
Since you store references to tags, you need to fetch the tag by slug first:
TagsCollection.find({slug:'tag-name'}, (err, tags)...)
then filter by tag._id:
var query = {
'tags.tag': new ObjectId(tag._id)
}
or
var query = {
'tags.tag': {'$in": [new ObjectId(tag._id), ....]}
}
if you have more than 1 tag matching the slug.
Honestly, it would be way more efficient, if you store tags directly in the document, instead of storing references.

Removing An Object From An Array ($pull doesn't seem to work)

I'm trying to remove a lesson based on lesson_id from the following.
{
"_id" : ObjectId("5807f3f"),
"title" : "Title",
"lessons" : [
{
"lesson_id" : ObjectId("58073"),
"_id" : ObjectId("58074")
},
{
"lesson_id" : ObjectId("5807f5"),
"_id" : ObjectId("5807f6")
},
{
"lesson_id" : ObjectId("58077"),
"_id" : ObjectId("5807f4")
}
],
"__v" : 0
}
I've tried $pull and $unset, but with both my code seems to just set lessons.lesson_id to null and keep the lessons._id
Is there anyway to remove both from the object?
module.exports.deleteLessonFromClass = function(id, lesson_id, callback){ Class.update(
{'_id': id},
{ $unset: {lessons: {lesson_id: lesson_id}}},
callback
) }
Try the following query:
db.collection.update(
{ "_id" : <id> },
{ $pull : { "lessons" : { "lesson_id" : <lesson_id> } } }
);
This will find a document by <id> and remove its <lesson_id> from its lessons array.
Hope this helps.

How to remove a document from a deep collection using mongodb query?

{
"_id" : ObjectId("5728443e04b2e5b42073a361"),
"user_id" : ObjectId("5728443e04b2e5b42073a35f"),
"main" : {
"data_to_save" : [
{
"user_profile_id" : ObjectId("572844bc04b2e5b42073a362")
"_id" : ObjectId("57284ab183e62da222e1378b"),
"details" : [
{
"amount" : 10000,
"_id" : ObjectId("57284f42e4560b66238a637c"),
"modified" : ISODate("2016-05-03T12:42:02.927Z"),
"created" : ISODate("2016-05-03T12:42:02.927Z")
},
{
"amount" : 4000
"_id" : ObjectId("57284f42e4560b66238a637b"),
"modified" : ISODate("2016-05-03T12:42:02.927Z"),
"created" : ISODate("2016-05-03T12:42:02.927Z")
}
]
}
]
}
"__v" : 0
}
In database schema of mongoDB. Here I am want to remove perticular document of a perticular collection.
like I want to remove first document of details collection. I have _id ( 57284f42e4560b66238a637c ) of that perticular document.
Tried
connection.collection.remove( { 'main.data_to_save.0.details.$._id' : id }, function ( err, removed ) {});
You could use the $pull operator to remove one or more entries from an array of documents:
// mainDocId = ObjectId("5728443e04b2e5b42073a361")
// id = ObjectId("57284f42e4560b66238a637c")
connection.collection.update(
{ _id: mainDocId},
{ $pull: {'main.data_to_save.0.details' : id } }, function ( err, result ) {
});

Resources