Return Array of Populated Objects in Mongoose - mongodb

I have a DB for a forum with 3 collections: Threads, Posts, Comments.
I have a GET request to return an individual forum thread that populates each thread with user's posts, and each user post with any comments that were made on it which is working as shown below:
router.get('/:id', (req, res) => {
Threads
.findById(req.params.id)
.lean()
.populate({path: 'posts'})
.exec(function(err, docs){
var options = {
path: 'posts.comments',
model: 'comments'
};
if(err) return res.json(500);
Threads.populate(docs, options, function(err, thread){
res.json(thread);
})
})
})
When this GET request is made it will return a forum thread like so:
{
"_id": "5924ad549a08ed4e70a9c89f",
"title": "Testing Full Schemas",
"author": "Mongoose",
"content": "Schema Content",
"posts": [
{
"_id": "5924ad999a08ed4e70a9c8a0",
"content": "New Schema Post",
"user": "Mongodb",
"comments": [
{
"_id": "5924ae489a08ed4e70a9c8a1",
"comment": "New Schema Content",
"user": "Matt",
"likes": 0,
"created": "2017-05-25T12:41:58.319Z"
}
]
}
Now I need a GET request to return an array of ALL threads (router.get('/')) with each threads posts and comments to be populated. I tried to replace:
Threads
.findById(req.params.id)
with
Threads
.find(req.params.id)
but it is not working. Does anyone have an idea of how this could be accomplished?

To return all the threads, simply use find without any match condition in it.
Also, populate posts and 'posts.comment' in the find query itself, you don't need to do it in the callback of the find.
use population across multiple levels
**Try this:
Threads.find({})
.populate({
path:'posts',
populate :{
path : comments
}
})
.exec(function(err,docs){
//docs is the array of all the Threads, with posts and comments populated within it
})
Read Mongoose Documentation on Populate and Nested Population for detailed information. ( Search for Populating across multiple levels)

findById and findOne returns a single document, where find returns a cursor. Once you go through the cursor of find, you are at the end, and there are no more documents.
Using find query:-
ModelName.find({_id:req.params.id})
.populate({
path:'posts',
populate :{
path : comments
}
},(error,data)=>{
if(error){
res.json(error);
}
else{
res.json(data);
}
})
Using findById query:-
ModelName.findById(req.params.id)
.populate({
path:'posts',
populate :{
path : comments
}
},(error,data)=>{
if(error){
res.json(error);
}
else{
res.json(data);
}
})

Related

findOneAndUpdate - document query > 1000

So I have a collection that has over 1million documents clearly, I don't need to search 1000 or more documents as it should only be updating the latest document.
const nowplayingData = {"type":"S",
"station": req.params.stationname,
"song": data[1],
"artist": data[0],
"timeplay":npdate};
LNowPlaying.findOneAndUpdate( nowplayingData,
{ $addToSet: { history: [uuid] } },
{ upsert: true, sort: {_id:-1} },
function(err) {
if (err) {
console.log('ERROR when submitting round');
console.log(err);
}
});
I have added a sort on it, so that it is able to get the latest one first, but if the document is not in there and it's the first time the document is being added then the way the script is written will query all documents to find.
When really it only needs to look at the last say 100 documents or even better if timeplay is in the last 5 minutes.
You can do something like:
const nowplayingData = {
"type":"S","station": req.params.stationname, "song": data[1], "artist": data[0],
"timeplay":{$gte: beforeFiveMin}};
But this will create a new document almost every time...so you will need to maintain it...

can't update DB using put request in express.js

I'm trying to update the languages_known through post request to the mongodb collection using the body of the request but its not updating i'm newbie any help would be really appreciated.
mongodb document :
{
"_id": {
"$oid": "5d63e81c342987154cdc698e"
},
"name": "anjana",
"email": "anju#gmail.com",
"age": "22",
"languages_known": [
"Bengali",
"Kannada"
],
"phone": "684684684846"
}
server code :
app.put('/students/add',function(req,res){
var myobj={
$set:{_id:require('mongodb').ObjectID(req.body.id),languages_known:req.body.remove}
}
db.collection('students').updateOne({languages_known:req.body.add},myobj,function(err,result){
if(err){throw err}
console.log("updated")
})
})
request body :
{
"id":"5d63e81c342987154cdc698e",
"remove": ["Bengali", "Kannada"],
"add": ["Tamil", "Punjabi"]
}
I've expected to update the languages_known field using this req through postman to this id
Ok this issue is with the query, you can't update _id of a document like that, also as your requirement is not to do that, Please try this :
server code :
// replace languages_known with new languages based on _id, in case if you wanted to update the array you can use $push
app.put('/students/add', function (req, res) {
const id = require('mongodb').ObjectID(req.body.id)
let updateQuery = {
$set: { languages_known: req.body.add }
}
db.collection('students').updateOne({ _id: id }, updateQuery, function (err, result) {
if (err) { throw err }
console.log("updated")
})
})

Can anyone generate mongodb query for my scenario

I am new to MongoDB and using Mongoose to manage data to and from MongoDB. I have a collection having below structure:
var post= new Schema({
message: String,
created_by_user_id: mongoose.Schema.Types.ObjectId,
created_at: Date,
likes: [new Schema({liked_by_user_id: mongoose.Schema.Types.ObjectId})]
});
Below is the above collection with dummy documents:
[{
"_id": "5c0254c13a22f222ceb861ad",
"message": "from pppr",
"created_by_user_id": "5c0253e9a53bed2165c0625c",
"likes": [
{
"_id": "5c027a6fff5fcb5ab180e20c",
"liked_by_user_id": "5c0253e9a53bed2165c0625c"
},
{
"_id": "5c028e46abc09775c10d767b",
"liked_by_user_id": "5c0234c1d8832b6af3b4f4a6"
}
],
"created_at": "2018-12-01T09:30:41.943Z",
"__v": 0
},
{
"_id": "5c0254c13a22f222ceb861ad",
"message": "from pppr",
"created_by_user_id": "5c0253e9a53bed2165c0625c",
"likes": [
{
"_id": "5c027a6fff5fcb5ab180e20c",
"liked_by_user_id": "5c0253e9a53bed2165c0625c"
},
{
"_id": "5c028e46abc09775c10d767b",
"liked_by_user_id": "5c0234c1d8832b6af3b4f4a6"
}
],
"created_at": "2018-12-01T09:30:41.943Z",
"__v": 0
}]
Now, I am trying to get all documents along with status which will indicate that, whether I have liked the respective post or not. In request, I am also send my user id.
Basically, On my wall, system should show all the posts created by either me or by my friends along with extra status in each document which will show whether I liked the respective post or not.
I am saving user friends in separate collection named as "userfriends". The structure of this collection is given below:
var userfriends = new Schema({
user_id_1: mongoose.Schema.Types.ObjectId,
user_id_2: mongoose.Schema.Types.ObjectId,
created_at: Date
});
I just want to get all posts along with that extra field. So, you can ignore the userfriends collection this is just for guiding you more.
Can any one help me on this? What will be the query which can fulfill my requirement?
Thanks in Advance
You can use $addFields along with the $in aggregation operator
db.collection.aggregate([
{ "$addFields": {
"status": { "$in": [mongoose.Types.ObjectId(userId), "$likes.liked_by_user_id"] }
}}
])
It will add a new fields to your every post document with the boolean value

How to save / update multiple documents in mongoose

I am reading all documents of a specific schema from Mongoose. Now in my program I am doing some modifications to the results I got from Mongoose over time. Something like this:
var model = mongoose.model("Doc", docSchema);
model.find(function(err, result){
// for each result do some modifications
});
How can I send all the results back to the database to be saved? Currently I am iterating the documents and doing a save() on every document. I think there must be a better way. But currently I only find information on updating documents IN the database without returning them. Or bulk updates which do the SAME to update to each document.
You can use update query with multi:true which update all documents in your db.
please find below reference code,
model.update({ "_id": id }, { $set: { "Key": "Value" } }, { multi: true }, function (err, records) {
if (err || !records) {
return res.json({ status: 500, message: "Unable to update documents." });
} else {
return res.json({ status: 200, message: "success" });
}
});
If you are trying to make the same change to each document in the results, you could do something like this:
model.update({ _id: { $in: results.map(doc=>doc._id) }}, { yourField: 'new value' }, { multi: true })

Mongoose query where value is not null

Looking to do the following query:
Entrant
.find
enterDate : oneMonthAgo
confirmed : true
.where('pincode.length > 0')
.exec (err,entrants)->
Am I doing the where clause properly? I want to select documents where pincode is not null.
You should be able to do this like (as you're using the query api):
Entrant.where("pincode").ne(null)
... which will result in a mongo query resembling:
entrants.find({ pincode: { $ne: null } })
A few links that might help:
The mongoose query api
The docs for mongo query operators
$ne
selects the documents where the value of the field is not equal to
the specified value. This includes documents that do not contain the
field.
User.find({ "username": { "$ne": 'admin' } })
$nin
$nin selects the documents where:
the field value is not in the specified array or the field does not exist.
User.find({ "groups": { "$nin": ['admin', 'user'] } })
I ended up here and my issue was that I was querying for
{$not: {email: /#domain.com/}}
instead of
{email: {$not: /#domain.com/}}
Ok guys I found a possible solution to this problem. I realized that joins do not exists in Mongo, that's why first you need to query the user's ids with the role you like, and after that do another query to the profiles document, something like this:
const exclude: string = '-_id -created_at -gallery -wallet -MaxRequestersPerBooking -active -__v';
// Get the _ids of users with the role equal to role.
await User.find({role: role}, {_id: 1, role: 1, name: 1}, function(err, docs) {
// Map the docs into an array of just the _ids
var ids = docs.map(function(doc) { return doc._id; });
// Get the profiles whose users are in that set.
Profile.find({user: {$in: ids}}, function(err, profiles) {
// docs contains your answer
res.json({
code: 200,
profiles: profiles,
page: page
})
})
.select(exclude)
.populate({
path: 'user',
select: '-password -verified -_id -__v'
// group: { role: "$role"}
})
});
total count the documents where the value of the field is not equal to the specified value.
async function getRegisterUser() {
return Login.count({"role": { $ne: 'Super Admin' }}, (err, totResUser) => {
if (err) {
return err;
}
return totResUser;
})
}
Hello guys I am stucked with this. I've a Document Profile who has a reference to User,and I've tried to list the profiles where user ref is not null (because I already filtered by rol during the population), but
after googleing a few hours I cannot figure out how to get this. I
have this query:
const profiles = await Profile.find({ user: {$exists: true, $ne: null }})
.select("-gallery")
.sort( {_id: -1} )
.skip( skip )
.limit(10)
.select(exclude)
.populate({
path: 'user',
match: { role: {$eq: customer}},
select: '-password -verified -_id -__v'
})
.exec();
And I get this result, how can I remove from the results the user:null colletions? . I meant, I dont want to get the profile when user is null (the role does not match).
{
"code": 200,
"profiles": [
{
"description": null,
"province": "West Midlands",
"country": "UK",
"postal_code": "83000",
"user": null
},
{
"description": null,
"province": "Madrid",
"country": "Spain",
"postal_code": "43000",
"user": {
"role": "customer",
"name": "pedrita",
"email": "myemail#gmail.com",
"created_at": "2020-06-05T11:05:36.450Z"
}
}
],
"page": 1
}
Thanks in advance.