How to add object to a nested array in mongoDB and nodeJS - node.js

I have no clue how can I push an object to a nested array
this is the Board document:
{
"boardMembers": [
"5f636a5c0d6fa84be48cc19d"
],
"boardLists": [
{
"cards": [],
"_id": "5f6387e077beba2e3c15d15a",
"title": "list one",
"__v": 0
}
],
"_id": "5f63877177beba2e3c15d159",
"boardName": "board1",
"boardPassword": "123456",
"boardCreator": "5f636a5c0d6fa84be48cc19d",
"g_createdAt": "2020-09-17T15:57:37.616Z",
"__v": 2
}
I need to push a task inside the cards array (to a specific list with ID)
here is the code:
outer.post("/add-task/:id", auth, boardAuth, async (req, res) => {
const listId = req.params.id;
const board = await Board.findOne({ _id: req.board._id });
if (!board) return res.status(404).send("no such board");
const list = await List.findOne({ _id: listId });
if (!list) return res.status(404).send("List not found");
const task = new Task({
text: req.body.text,
});
board.boardLists.map((list) => {
if (listId.toString() === list._id.toString()) {
list.cards.push(task);
} else {
console.log("no task");
}
});
await board.save();
res.send(board);
});
now the problem is when I make the request in postman its shows me the task inside the cards array i want but its not saving it to the mongoDB

You're using array.map() but:
Nothing is returned in the callback of map(), which will return an array with each element undefined;
You aren't assigning the array returned by map() to anything.
So, you can use array.map() to return an array in which the task is pushed to the desired list in board.boardLists like so:
board.boardLists = board.boardLists.map((list) => {
if (listId.toString() === list._id.toString()) {
return {
...list,
cards: list.cards.concat(task)
}
} else {
return list
}
});

Related

toArray is not a function in mongodb,mongoose

to Array is not a function in mongo database, mongoose, node.js
`getCartProducts: (userId) => {
return new Promise(async (resolve, reject) => {
let cart Items = await db.cart.aggregate([
{`your text`
$match: { user: user Id }//matched with the id
},
{
$lookup: {
from: "db.products",
let: { proList: '$products' },
pipeline: [
{
$match: {
$expr: {
$in: ["$_id", '$$proList']
}
}
}
],
as: 'cart Items' //converted as cart Items name
}
}
]).`to array`()
resolve(`cart Items`)
})
}
db. cart. aggregate().to Array is not a function
I tried to remove the to array but it shows as un defined
Issue is you're doing toArray() on promise,
it should be something like this.. you don't need to create custom promise..
const getCartItems = () => {
// ...
const items = await db.cart.aggregate([...])
return items.toArray();
...
}

Getting an {"message":"Invalid update pipeline operator: \"_id\""} error

I am trying to update two rows in my players table based on the id. I am trying to use the updateMany method where id can be found in an array of id's but I am getting the {"message":"Invalid update pipeline operator: \"_id\""} error. I checked the array to make sure it is valid id's. Here is my code
const winningTeam = asyncHandler(async (req, res) => {
req.body.forEach((element) => {
element.wins += 1;
element.lastPlayed = Date.now();
element.percentage = (element.wins / (element.wins + element.wins)) * 1000;
});
let usersId = [];
usersId.push(req.body[0]._id);
if (req.body.length === 2) {
usersId.push(req.body[1]._id);
}
const player = await Player.updateMany({ _id: { $in: usersId } }, req.body);
if (player) {
res.status(200).json(player);
} else {
res.status(400);
throw new Error("Invalid Data");
}
});
You should use $set property for the update parameter. I'm not sure about the structure of your req.body but it should be something like this:
Player.updateMany({ _id: { $in: usersId } }, {$set: req.body});
instead of this:
Player.updateMany({ _id: { $in: usersId } }, req.body);
Take a look at docs for updateMany

Remove object array items by comparing object array from mongodb

There is document which is having array of object inside.
Like
Objectid('')
fruits : [{_id:'2'},{_id:'3'},{_id:'4'}]
I want to delete these items fruits_id = [{_id:'3'},{_id:'4'}].
fruit_group.updateOne(
{collection_id: collection_id},
{$pullAll: {"fruits": fruits_id}}
)
so far i found below logic which i think is not efficient.
routes.post('/removeFruits', async (request, response, next) => {
var post_data = request.body;
var collection_id = post_data.collection_id;
var fruits_ids = JSON.parse(post_data.fruits_ids);
var prev_fruits;
await fruit_group.findOne({'collection_id': collection_id}, function (err, result) {
if (err) {
console("Some error occurred");
response.json({'message': "Some error occurred", 'result': 'false'});
}
prev_fruits = result.fruits;
});
for (var i = 0; i < fruits_ids.length; i++) { // this will delete all occurring items from array
var key = fruits_ids[i].user_id;
prev_fruits.filter(x => x.user_id === key).forEach(x => prev_fruits.splice(prev_fruits.indexOf(x), 1));
}
await fruit_group.updateOne({'collection_id': collection_id}, {$set: {'fruits': prev_fruits}}, function (err, result) {
if (err) {
response.json({'message': "Some error occurred", 'result': 'false'});
}
response.json({'message': 'Deletion successfully', 'result': 'true'});
});
});
is there anyway to achieve the same result?
Assuming fruits_id = [{ _id: '3' }, { _id: '4' }], you could do something like this using $pull and $in:
await fruit_group.updateOne({'collection_id': collection_id}, { $pull: { fruits: { $in: fruits_id }}})
This follows the example of removing all items that equal a specified value.

MongoDb: How to only update objects whose id are the same than new object's pushed in an array?

I have an array of images in a mongo database that looks like this:
pictures: [
{id: "1", url: "url1/file/lala"},
{id: "2", url: "url2/fila/lili"},
]
When a user wants to replace an image, the new image correctly replaces the former one in my cdn storage. I then receive a new url for this image. I need to either add the new object {id: "3", url: "url3/file/lolo" for example) to my pictures array if it doesn't exist in it, or to update/replace the objects whose id are the same than my new object(s).
How would you do that?
For the moment, I just have:
router.post("/upload-images", upload.array("image"), async (req, res) => {
const { userId } = req.body;
try {
if (req.files) {
let newProfilePicture = null;
let otherPictures = [];
req.files.forEach(({ path, originalname }) => {
// handle upload here
return originalname === "main"
? (newProfilePicture = res.secure_url)
: otherPictures.push({ id: originalname, url: res.secure_url });
}
);
});
const user = await User.findByIdAndUpdate(
userId,
{
profilePicture: newProfilePicture && newProfilePicture,
// TODO ADD OTHER PICTURES
},
{ new: true }
);
res.send("upload images success");
}
} catch (err) {
return res.send("upload images failed");
}
});
Thanks for your help!

how to query mongodb based on object to get documents that contains one or more equal properties (Search)

Im trying to figure out how to Post a search object to mongo, and find all documents that matches one or more properties stated in the search object.
eg if i have post a json object as this:
// searchObject
{
"kind": "employee"
"name": "casper",
"email": "daniel#mail.com"
}
i want to get all documents that contains "name": "casper"or "email":"daniel#mail.com"or both from the employee collection.
this is what i have so far. but i dont know how to loop through my properties.
router.post('/search', async (ctx) => {
const searchObject = Object.assign(ctx.request.body);
const collection = searchObject.kind
const result = await store[collection].find({
$and: [{ searchObject }]
})
console.log('result', result)
})
Try this:
router.post('/search', async ctx => {
const { kind, ...searchObject } = ctx.request.body;
const collection = searchObject.kind;
const conditions = Object.keys(searchObject).reduce((acc, key) => {
acc.push({ [key]: searchObject[key] });
return acc;
}, []);
const result = await store[collection].find({
$or: conditions,
});
console.log('result', result);
});
add if (key !== "kind") condition in reduce function
router.post('/search', async ctx => {
const searchObject = ctx.request.body;
const collection = searchObject.kind;
const conditions = Object.keys(searchObject).reduce((acc, key) => {
if (key !== "kind") acc.push({ [key]: searchObject[key] });
return acc;
}, []);
const result = await store[collection].find({
$or: conditions,
});
console.log('result', result);
});

Resources