How to add to array in MongoDB document with mongoose? - node.js

I've got a collection of spellbooks in a mongodb. One of my API calls in express through mongoose is a PUT where the user provides the ID of the document and then a body that contains an array of spells. I want to update the array of spells in the spellbook document with the array brought in from the client.
Here's what the document looks like:
{
"_id": {
"$oid": "56f999342c2bdee43869c33b"
},
"name": "malagar22",
"username": "zak",
"spells": [
"56bd4da932c3b8e88e3c113a",
"56bd4da932c3b8e88e3c113b"
],
"__v": 0
}
Here's what my API call looks like:
app.put('/api/spellbook/:id', function (req, res) {
Spellbook.findById(req.params.id, function(err,spellbook) {
if (err) {
res.json({info:'error during find spellbook',error:err});
};
if (spellbook) {
_.merge(spellbook, req.body);
spellbook.save(function(err) {
if (err) {
res.json({info:'error updating spellbook',error:err});
};
res.json({info:'spellbook updated successfully'});
});
} else {
res.json({info:'spell not found'});
}
})
});
As you can see, I'm finding the spellbook that matches the ID. Then I'm doing a lodash merge with the request body, which I imagine would match the spells array in the document with the spells array in the body, which I'll post below. Then we update.
Here's my request:
{
"spells":[
"56bd4daa32c3b8e88e3c1148"
]
}
I'm getting the success callback, but when I check the database, the document isn't being updated. Sorry if this is really simple. I'm an MS SQL guy and this is my first time using Express and Mongo.

Related

Match query for json object mongodb data returning empty array

I'm building REST APIs in node.js using express.js library.
For the embedded data stored in mongodb as json object, I'm trying to get specific data by filtering, thereby using the aggregate match to achieve so.
For the users collection, I've the data as below
[
{
unique_key:"1",
user_form:
{
user_details:
{
first_name:"Tely",
last_name:"Zed"
}
}
},
{
unique_key:"2",
user_form:
{
user_details:
{
first_name:"Rock",
last_name:"Monty"
}
}
}
]
I want to get data of user by searching name. So I'm using aggregate method and then using match operator to achieve it.
User is the name of the model.
For filtering I'm using below aggregate method on User model.
User.aggregate([
{
$match: {
user_form:
{
user_details:
{
first_name: req.body.user_form.user_details.first_name
}
}
}
}
])
.exec(function(err,filteredUsers){
if(filteredUsers) {
console.log(filteredUsers);
res.json({
"msg": "Successfully gets the filtered users",
"data": filteredUsers,
"success": true
});
} if(err){
res.json({
"msg":"Error occured while filtering users",
"error": err ,
"success":false
});
}
})
//Now when I'm posting request from postman with searching with first_name as Rock in postman //body as shown below.
{
user_form:
{
user_details:
{
first_name:"Rock"
}
}
}
//So upon hitting send, I'm getting below response in postman, so I'm not able to get filtered //data instead getting an empty array.
{
"msg": "Successfully gets the filtered users",
"data": [],
"success": true
}
So please tell what should I do to filter data .
Used dot notation to query for subdocument.
db.users.aggregate([
{$match:{"user_form.user_details.first_name":"Rock"}}]).pretty()
Output:
{
"_id" : ObjectId("63c01a42232f174edd983fbf"),
"unique_key" : "2",
"user_form" : {
"user_details" : {
"first_name" : "Rock",
"last_name" : "Monty"
}
}
}
The mistake I did was I kept a space in "first_name" like "first_name " while inserting the document, so that's why I wasn't able to get filtered data by dot notation method also, so later I did found by same query.

Modify data coming from MongoDB query in Node.js

I have a simple query that fetches data from MongoDB. The query returns an array of objects in which the seller ID matches. I want to change a particular field in all of the returned objects. Is there a more efficient way than to use map?
I have added the query here:
Order.find({ sellerId: sId })
.populate("address")
.exec((err, result) => {
if (err) {
return res.status(403).json({
error: err,
});
}
return res.status(200).send(result);
});
And this is the API response:
[
{
"orderDate": "2022-04-21T13:16:22.198Z",
"sellerId": "6212072976836b7c70d3dcb1",
"__v": 0
}
]
I want to change order date for each object in the object of arrays returned.

Express restful api expecting json array

I'm trying to integrate an Excel spreadsheet with my application using an node.js Express Restful Api. My API already accepts simple json like:
{
"num": "1",
"name": "Adams"
}
But now i need to send array of objects like:
[
{
"num": 1,
"name": "Adams"
},
{
"num": 2,
"name": "Phillips"
}
]
I'm using mongoose to connect to a mongoDB server and already the following function connected to a route in my api to accept single objects:
create_a_budget: function (req, res) {
var budget = new budgetModel({
user_id : req.body.user_id,
seq_budget : req.body.seq_budget,
date_done : req.body.date_done,
num_budget : req.body.num_budget,
medium : req.body.medium,
client_name : req.body.client_name,
email : req.body.email
});
budget.save(function (err, budget) {
if (err) {
return res.status(500).json({
message: 'Error when creating budget',
error: err
});
}
return res.status(201).json(budget);
});
}
But i don't have a clue about how to treat the array
You can simply pass an array of documents received from mongodb in res.json. res.json() will handle array properly. You dont have to do anything else. Example of the same:-
db.budget.find(query, (err, budgets) {
if(err) {
// handle error
}
return res.status(200).json(budgets);
});

mongoose getting all from collection returns back an empty list

I created a new collection in my project and followed the same syntax for retrieving all users to retrieve all from this collection but I end up getting an empty array or list for some reason. Can someone please let me know why that is as I am fairly new to MongoDB. below is my code. the service is being called as I put a console.log before the query and it is called. Also saving data to the DB also works its just getAll I am having trouble doing. the collection only has one field which is account number.
In the service I have
async function getAll() {
return await accountdb.find({});
}
controller
function getAll(req, res, next) {
accountdbService.getAll()
.then(account => res.json(account))
.catch(err => next(err));
}
in the front end i have
getAll() {
return this.http.get<account[]>(`${environment.apiUrl}/account`);
}
and finally in the component
ngOnInit() {
this.loadAllAccounts();
}
private loadAllAccounts() {
this.AccountService.getAll().pipe(first()).subscribe(account => {
this.accounts = account;
console.log(this.accounts);
});
console.log(this.accounts);
}
postman response when calling api:
[
{
"_id": "5b89e647e1e6540ac28d68b1",
"logDataInput": "admin changed the status of user test2 to manager",
"__v": 0,
"id": "5b89e647e1e6540ac28d68b1"
},
{
"_id": "5b89e648e1e6540ac28d68b2",
"logDataInput": "admin changed the status of user test2 to User",
"__v": 0,
"id": "5b89e648e1e6540ac28d68b2"
},
{
"_id": "5b8a2a6b16206e0cae8c71ba",
"logDataInput": "admin deactivated user test2",
"__v": 0,
"id": "5b8a2a6b16206e0cae8c71ba"
}
]
network tool 2 api calls picture
Looks like you're sending wrong variable in response from getAll function.
.then(logTrack => res.json(account)
Chage this to
.then(logTrack => res.json(logTrack)
The reason is, the getAll() function is asynchronous, that is to say the code directly after may be executed before the subscribe function is.
It looks like your array is being set but, by checking it outside of the subscribe, you're checking it before it's been set.

Mongoose updating document with findOne() matches only wrong results

I have a collection of fixtures that 'belong' to a competitor and look something like this:
{
"_id": {
"$oid": "59dbdf6dbe628df3a80419bc"
},
"timeOfEntrance": "1507581805813",
"timeOfFinish": null,
"competitor": {
"$oid": "59db5a3f3d6119e69911a61a"
},
"__v": 0
}
My goal is to update only the document's timeOfFinish by sending a PUT request with competitor's ID as a param in the url and timestamp in the body. However I'm struggling to compose the update query.
The following is what I have currently, it never finds the right match and to my surprise it's always updating the wrong document.
fixtureController.put = (req, res) => {
const competitorId = req.params.id;
const timeOfFinish = req.body.timeOfFinish;
Fixture.findOne({'competitor.$oid': competitorId}, (err, fixture) => {
fixture.set({ timeOfFinish });
fixture.save()
.then(updatedFixture => {
return res.status(200).json({
success: true,
fixture: updatedFixture
})
})
.catch(err => {
return res.status(500).json({
message: err
});
});
});
};
Bit of a beginner in the MongoDB field, will appreciate your comments and solutions.
Turns out there was no need to specify the exact field in the match parameter. Mongoose matches by the id field automatically.
Fixture.findOne({'competitor': competitorId}, (err, fixture) => {
...
});

Resources