Loop inside mongo query - node.js

I'm new to MongoDB. And in my collection, I have an array of data. And at the user end, I also have an array. I want to match the user end array with the collection array if any of the elements match with the collection array data, the should be considered as a result. Below is my collection :
{
"_id": {
"$oid": "5f5b2f728cae440be88437f0"
},
"course": ["5f378f6aaf169e22d01d32d4", "5f2ba101f012a62ed011f3ae"],
"access": 1,
"status": 1,
"title": "Simplification",
"createdAt": {
"$date": "2020-09-11T08:04:02.896Z"
},
"updatedAt": {
"$date": "2020-09-11T08:04:02.896Z"
},
"__v": 0
}
And let's suppose I have an array on the user end like:-
var my_courses=["5f378f6aaf169e22d01d32d4","5f6449e726f13210b026635d"];
I want to match this array with the collections course column array. Either the array elements match with the collection or the access should be 0.
Here is my mongo query:-
const videos=await Vimeo_Videos
.find({status: 1},'$and':[ { '$and':[ { course: { '$elemMatch': {'$eq':'5f378f6aaf169e22d01d32d4' } } } ],'$or': [ { access: 0 } ] } ] }).limit(4)
How can I run a loop inside the query to match all array elements with a collection array? Please suggest me solution how can I do that.

If you are sure about the elements in the array, you could write like this-
{ course: {$all:['5f378f6aaf169e22d01d32d4','5f6449e726f13210b026635d']} }
So, your code would be-
const videos=await Vimeo_Videos.find({ course: {$all: '5f378f6aaf169e22d01d32d4','5f6449e726f13210b026635d']} })
Not sure if this what you are looking for. Hope it helps some way!

Related

how can i sort data with a array element in mongodb without using unwind

this is my sample data in this I have a userId and a array "watchHistory", "watchHistory" array contains the list of videos that is watched by the user :
{
"_id": "62821344445c30b35b441f11",
"userId": 579,
"__v": 0,
"watchHistory": [
{
"seenTime": "2022-05-23T08:29:19.781Z",
"videoId": 789456,
"uploadTime": "2022-03-29T12:33:35.312Z",
"description": "Biography of Indira Gandhi",
"speaker": "andrews",
"title": "Indira Gandhi",
"_id": "628b45df775e3973f3a670ec"
},
{
"seenTime": "2022-05-23T08:29:39.867Z",
"videoId": 789455,
"uploadTime": "2022-03-31T07:37:39.712Z",
"description": "What are some healthy food habits to stay healthy",
"speaker": "morris",
"title": "Healthy Food Habits",
"_id": "628b45f3775e3973f3a670"
},
]
}
I need to match the userId and after that i need to sort it with "watchHistory.seenTime", seenTime field indicates when the user saw the video. so i need to sort like the last watched video should come first in the list.
I don't have permission to use unwind so can any one help me from this. Thank you.
If you are using MongoDB version 5.2 and above, you can use $sortArray operator in an aggregation pipeline. Your pipeline should look something like this:
db.collection.aggregate(
[
{"$match":
{ _id: '62821344445c30b35b441f11' }
},
{
"$project": {
_id: 1,
"userId": 1,
"__v": 1,
"watchHistory": {
"$sortArray": { input: "$watchHistory", sortBy: { seenTime: -1 }}
}
}
}
]
);
Please modify the filter for "$match" stage, according to the key and value you need to filter on. Here's the link to the documentation.
Without using unwind, it's not possible to do it via an aggregation pipeline, but you can use update method and $push operator, as a workaround like this:
db.collection.update({
_id: "62821344445c30b35b441f11"
},
{
$push: {
watchHistory: {
"$each": [],
"$sort": {
seenTime: -1
},
}
}
})
Please see the working example here

How to match and join results between two resolvers in one graphql query?

I have two resolver.
The one is Company resolve that return the company details like id, name and list of documents ids, like this example:
{
"data": {
"companyOne": {
"name": "twitter",
"documents": [
"5c6c0213f0fa854bd7d4a38c",
"5c6c02948e0001a16529a1a1",
"5c6c02ee7e76c12075850119",
"5c6ef2ddd16e19889ffaffd0",
"5c72fb723ebf7b2881679ced",
"5c753d1c2e080fa4a2f86c87",
...
]
}
}
}
And the another resolver gets me all the details of documents like this example:
{
"data": {
"documentsMany": [{
"name": "doc1",
"_id": 5c6c0213f0fa854bd7d4a38c,
}, {
"name": "doc2",
"_id": 5c6c02948e0001a16529a1a1,
},
...
]
}
}
How to match every data.companyOne.documents[id] to data.documentsMany[..]._id? in the query level? is it possible to do this graphql?
The expect results should be when I run the companyOne query (without change the code - just in the query level) it's should return with documents as object instead of array of string ids.
maybe something like?
query {
companyOne {
name,
documents on documentsMany where _id is ___???
}
}

MongoDB is returning all Results in the find function [duplicate]

This question already has answers here:
Retrieve only the queried element in an object array in MongoDB collection
(18 answers)
Closed 3 years ago.
I'm trying to perform a simple find using MongoDB, I'm new on it, so I don't know what is wrong, but it seems that it's always bringing all the results without filtering it.
You can run the code here and see what is happening:
https://mongoplayground.net/
Collection - Paste it here https://mongoplayground.net/ - FIRST Text Area
[
{
"collection": "collection",
"count": 10,
"content": [
{
"_id": "apples",
"qty": 5
},
{
"_id": "bananas",
"qty": 7
},
{
"_id": "oranges",
"qty": {
"in stock": 8,
"ordered": 12
}
},
{
"_id": "avocados",
"qty": "fourteen"
}
]
}
]
Find - Paste it here https://mongoplayground.net/ - SECOND Text Area
db.collection.find({
"content.qty": 5
})
Check the results and you will see the entire JSON as a result.
What Am I doing wrong? Thanks!
You can use $filter with $project after your $match in order to get just one item from the array:
db.collection.aggregate([
{ $match: { "content.qty": 5 }},
{
$project: {
collection: 1,
count: 1,
content: {
$filter: {
input: "$content",
as: "item",
cond: { $eq: [ "$$item.qty", 5 ]
}
}
}
}
}
])
Without having to unwind etc. You are getting all since $find returns the first document which matches and in your case that is the main doc.
See it working here
First, the query is bringing back what it should do. it bring you the document that satisfy your query, try to add element or more in the array you search in to see the difference.
Secondly, what you want to reach - to get only the specific elements in the nested array - can be done by aggregation you can read in it more here:
https://docs.mongodb.com/manual/aggregation/

Mongoose : how to set a field of a model with result from an agregation

Here is my sample :
Two simple Mongoose models:
a Note model, with among other fields an id field that is a ref for the Notebook model.
a Notebook model, with the id I mentioned above.
My goal is to output something like that:
[
{
"notes_count": 7,
"title": "first notebook",
"id": "5585a9ffc9506e64192858c1"
},
{
"notes_count": 3,
"title": "second notebook",
"id": "558ab637cab9a2b01dae9a97"
}
]
Using aggregation and population on the Note model like this :
Note.aggregate(
[{
"$group": {
"_id": "$notebook",
"notes_count": {
"$sum": 1
}
}
}, {
"$project": {
"notebook": "$_id",
"notes_count": "$notes_count",
}
}]
gives me this kind of result :
{
"_id": "5585a9ffc9506e64192858c1",
"notes_count": 7,
"notebook": {
"_id": "5585a9ffc9506e64192858c1",
"title": "un carnet court",
"__v": 0
}
}
Forget about __v and _id fields, would be easy to handle with a modified toJSON function.
But in this function neither doc nor ret params gives me access to the computed notes_count value.
Obviously, I could manage this in the route handler (parse result and recreate the datas that will be returned) but, is there a proper way to do that with mongoose ?
You can't use the aggregate method to update. As you have noted, you'll need to use output from the aggregate constructor to update the relevant documents.
As the Mongoose aggregate method will return a collection of plain objects, you can iterate through this and utilise the _id field (or similar) to update the documents.

How do you delete a Json object by id in node Mongodb?

i have a Mongodb collection named "EVENTS" and in the collection i have an object of array which looks like this:
{
"Events":[
{
"_id":"53ae59883d0e63aa77f7b5b2",
"Title":"Title Blank",
"Desc":"Description Blank",
"Date":"2014-06-04 00:30",
"Link":"http://googleparty.com",
"Event":"Victoria Centre",
"dateCreated":"28/6/2014 06:58"
},
{
"_id":"53ae59883d0e63aa77f7b5b3",
"Title":"Hello World",
"Desc":"hello",
"Date":"2014-06-04 00:30",
"Link":"http://linkedinparty.com",
"Event":"social",
"dateCreated":"30/2/2014 11:10"
}
]
}
how would i delete an object by id in node.js so " delete(53ae59883d0e63aa77f7b5b2)" will yield this:
{
"Events":[
{
"_id":"53ae59883d0e63aa77f7b5b3",
"Title":"Hello World",
"Desc":"hello",
"Date":"2014-06-04 00:30",
"Link":"http://linkedinparty.com",
"Event":"social",
"dateCreated":"30/2/2014 11:10"
}
]
}
Regards
If all you really want to do is "empty" the array then you just need to use the $set operator with an .update() and "set" the array as an empty one:
db.collection.update({},{ "$set": { "Events": [] } },{ "mutli": true})
So the .update() operation takes a "query" to select the documents in your collection, a blank query as shown selects everything. The "update" section contains the $set operation that just replaces the current "Events" field with an empty array.
The "multi" option there makes sure this is applied to every document that matches. The default is false and will only update the first document that matches.
For more specific operations removing selected array elements, look at the $pull operator. Your edit shows now that this is what you want to do:
db.collection.update(
{ "Events._id": ObjectId("53ae59883d0e63aa77f7b5b2") },
{ "$pull": { "Events": { "_id": ObjectId("53ae59883d0e63aa77f7b5b2") } } }
)
But your inclusion of arrays with _id fields seems to indicate that you are using mongoose, so the ObjectId values are cast automatically:
Model.update(
{ "Events._id": "53ae59883d0e63aa77f7b5b2" },
{ "$pull": { "Events": { "_id": "53ae59883d0e63aa77f7b5b2" } } },
function(err,numAffected) {
}
);

Resources