How to pluck out field value from arrays of object - node.js

I am retrieving data from mongoose database using node.js and express.
Currently, I am getting a response like this
[
{
"images": [
{
"link": "https://just-incase-from-a-far/yop.png"
},
{
"link": "https://main-link-test/lol.png"
}
]
},
{
"images": [
{
"link": "https://example-link/happy.jpg"
},
{
"link": "https://example-link/angry.jpg"
},
{
"link": "https://example-link/sad.png"
}
]
}
]
But I want a response like this
[
"https://just-incase-from-a-far/yop.png",
"https://main-link-test/lol.png",
"https://example-link/happy.jpg",
"https://example-link/angry.jpg",
"https://example-link/sad.png"
]
How can I achieve my desired response.
This is my code that gives me my response of array objects
exports.getProducts = async (req,res) => {
const result = await Product
.find({isEmpty:false})
.select("-_id -createdAt -__v -isEmpty")
.exec()
if(!result) return res.status(400).json({ data: 'No product found' });
if(result.err) return res.json({ err: err });
return res.json(result);
}

Just add a outer loop extracting the links
links = [];
result.forEach((obj) => {
links = [...obj.images.map((o) => o.link), ...links];
})

Related

How to pull out object heading from an array

I have a JSON response structure like this
{
"_id": "620e97d76ca392a43097cca6",
"user": "620295cbd67ece90802d2522",
"orderId": "EnrL7C",
"Items": [
{
"product": {
"name": "Fresh Salad",
"id": "61f2911723ff35136c98ad3e"
},
"quantity": 1,
"price": 1250,
"_id": "620e97d76ca392a43097cca7"
},
],
}
But i want the product not to be an object, so it should look like this
{
"_id": "620e97d76ca392a43097cca6",
"user": "620295cbd67ece90802d2522",
"orderId": "EnrL7C",
"Items": [
{
"name": "Fresh Salad",
"id": "61f2911723ff35136c98ad3e",
"quantity": 1,
"price": 1250,
"_id": "620e97d76ca392a43097cca7"
},
],
}
This is my code responsible for the response output
exports.getOrder = (req,res) => {
Order.findOne({orderId: 'EnrL7C'})
.populate("Items.product", "name")
.exec((error, order) => {
if(error) return res.status(400).json({ error });
if (order) {
return res.json(order);
}else{
return res.json(['No order found']);
}
});
Sometimes when I'm too lazy to look up all the mongoose documentation and figure out what version I'm on etc, I use the .lean() to just convert it to a normal JS object, which I'm way more comfortable with.
exports.getOrder = (req, res) => {
Order.findOne({ orderId: "EnrL7C" })
.lean() // add lean
.populate("Items.product", "name")
.exec((error, order) => {
if (error) return res.status(400).json({ error });
if (order) {
// fix the structure in javascript
order.Items = order.Items.map((item) => {
const flat = {
...item.product,
...item,
};
delete flat.product;
return flat;
});
return res.json(order);
} else {
return res.json(["No order found"]);
}
});
};
Let me know if that doesn't work, so I can update the answer.

sequelize Mysql data two between date all record show but some ... findall REST API ......simple problems

This my API Code .it work perfectly but missing my "startedDate":"2022-01-01", and
"endDate":"2022-01-31" … how I write the the function pls solved my problem and share your idea..
async getcurrentmonthorder2(req, res, next) {
try {
const {startedDate ,endDate} = req.body;
db.product.findAll({
attributes:[[sequelize.fn('sum',sequelize.col('profit_total')),'total']],
where : {"createdAt" : {[Op.between] : [new Date(startedDate).setHours(0,0,0,0) , new Date(endDate).setHours(23,59,59,999) ]}},
})
.then(list => {
res.status(200).json({ 'success': true, data: list });
})
.catch(function (err) {
next(err)
});
}
catch (err) {
res.status(500).json({ 'errors': "" + err });
}
}
#I have got output from postman..
{
"success": true,
"data": [
{
"total": "121",
}
]
}
#but I want to this output pls help share your idea
{
"success": true,
"data": [
{
"total": "121",
"startedDate":"2022-01-01",
"endDate":"2022-01-31"
}
]
}
my data
{id: 1, total: 20, profit_total: 15, createdAt: "2021-12-30T15:59:10.000Z",…}
Your problem comes from the attributes which you indicated in your query: You told SEQUELIZE to return only TOTAL. I suggest you this::
db.product.findAll({
attributes:[[sequelize.fn('sum',sequelize.col('profit_total')),'total'], 'startedDate', 'endDate'],
where : {
"createdAt" : {
[Op.between] : [new Date(startedDate).setHours(0,0,0,0), new Date(endDate).setHours(23,59,59,999) ]}
},
})

Firebase database collection returns empty array when trying to get all documents

I'm trying to get all documents from my database collection "posts" but I'm getting an empty array instead.
The strange thing is that I'm able to get all documents from another collection called "users" that has the same structure and using the exact same code.
I've spent days looking for an answer but I haven't been able to find the solution.
This is the request:
const db = admin.firestore();
exports.getAllPosts = (req, res) => {
db.collection('posts')
.orderBy('createdAt', 'desc')
.get()
.then(snapshot => {
let posts = [];
snapshot.forEach((doc) => {
posts.push({
id: doc.id,
body: doc.data().body,
author: doc.data().author,
createdAt: doc.data().timestamp,
voteScore: doc.data().voteScore
});
});
return res.json(posts);
})
.catch(err => {
console.error(err);
res.status(500).json({ error: err.code });
});
}
And this is the response:
[]
This is what my current collection looks like:
Posts collection screenshot
This the response that I get when I return "snapshot":
{
"_query": {
"_firestore": {
"_settings": {
"projectId": "readable-bf7a6",
"firebaseVersion": "9.6.0",
"libName": "gccl",
"libVersion": "4.10.0 fire/9.6.0"
},
"_settingsFrozen": true,
"_serializer": {
"allowUndefined": false
},
"_projectId": "readable-bf7a6",
"registeredListenersCount": 0,
"bulkWritersCount": 0,
"_backoffSettings": {
"initialDelayMs": 100,
"maxDelayMs": 60000,
"backoffFactor": 1.3
},
"_clientPool": {
"concurrentOperationLimit": 100,
"maxIdleClients": 1,
"activeClients": {},
"failedClients": {},
"terminated": false,
"terminateDeferred": {
"promise": {}
}
}
},
"_queryOptions": {
"parentPath": {
"segments": []
},
"collectionId": "posts",
"converter": {},
"allDescendants": false,
"fieldFilters": [],
"fieldOrders": [
{
"field": {
"segments": [
"createdAt"
]
},
"direction": "DESCENDING"
}
],
"kindless": false
},
"_serializer": {
"allowUndefined": false
},
"_allowUndefined": false
},
"_readTime": {
"_seconds": 1622395245,
"_nanoseconds": 513743000
},
"_size": 0,
"_materializedDocs": null,
"_materializedChanges": null
}
Notice how the request for the collection "users" works successfully:
const db = admin.firestore();
exports.getAllUsers = (req, res) => {
db.collection('users')
.orderBy('createdAt', 'desc')
.get()
.then(snapshot => {
let users = [];
snapshot.forEach((doc) => {
let users = [];
snapshot.forEach((doc) => {
users.push({
id: doc.data().userId,
email: doc.data().email,
handle: doc.data().handle
});
});
return res.json(users);
})
.catch(err => {
console.error(err);
res.status(500).json({ error: err.code });
});
}
And the response:
[
{
"id": "EPoHBxhQFUXbcL3TCVx1LdUG2nO2",
"email": "ruben#gmail.com"
},
{
"id": "RqEa3dEq8TSDcZYeolXafju67rB2",
"email": "user10#gmail.com"
},
{
"id": "dxveb4n2iMQej5Q14uprsKRxFp23",
"email": "user4#gmail.com",
"handle": "user4"
},
{
"id": "YQPzBPcsqlVZk9iJEuZTHKUNuVG2",
"email": "user2#gmail.com",
"handle": "user2"
},
{
"id": "CZ05BJxi3TUOpIrmBaz539OWlbC3",
"email": "user#gmail.com",
"handle": "user"
},
{
"id": "t0t83BVwt4gVgJkDv7HL1r1MaKr1",
"email": "userJose2#gmail.com",
"handle": "Jose"
}
]
This is what the users collection looks like in Firebase:
Users collection screenshot
Why is one collection failing when the other works fine and I'm using the same code? What am I missing here?
Thanks in advance and I hope I've made it as clear as possible. Please let me know if you need me to provide anything else.
Very simple my friend, your posts documents can't be ordered like this:
.orderBy('createdAt', 'desc')
Because the post documents does not have the createdAt property, but they have a timestamp property, you should use that property to order your posts like this:
.orderBy('timestamp', 'desc')
I hope that helps 👍
I am not answering directly to #Ruben Garcia Bri, but for future firebase developers who may run into the problem of getting empty documents, I also ran into the same problem, but I solved it by adding a field to the particular document I am trying to retrieve.
Sometimes the cause is because the documents you are trying to get have no field in them.
I mean that a document must have a field before the server can recognize it as an existing document.
So if you run into this problem, consider adding a field to that document before you can successfully retrieve it.

Add key on each json object in Promise

I have the following Promise and Promise.all which works and it returns a json object. However, I want to add a key for each return object.
as of now, it returns something
[value: {school object}, value:{students object}, value:{classroom object}]
desired output:
["schools": {school object }, {students object} , {classroom object} ]
Current Implementation:
new Promise((resolve, reject) => {
const school = getschool (webHost, dataSource, req);
const classRooms = getClassRooms(webHost, dataSource, req);
const students = getstudents (webHost,dataSource, req);
Promise.all([school ,classRooms,students ]).then((res) => {
resolve(res);
})
.catch((error) => {
logger.error(`${error}`);
reject(error);
});
});
classroom
{
"metadata": "metadata",
"value": [
{
"class_id": "171717",
"teacher_name": "Science"
}
]
}
School object
{
"metadata": "metadata",
"value": [
{
"id": "2345354",
"schoolName": "Memorial High School"
}
]
}
Student json
{
"metadata": "metadata",
"value": [
{
"id": "1234",
"studentName": "Beck"
},
{
"id": "5678",
"studentName": "Jeck"
}
]
}
Desired Output:
[
{
"class_id":"171717",
"teacher_name":"Science",
"id":"2345354",
"schoolName":"Memorial High School",
"Students":[
{
"id":"1234",
"studentName":"Beck"
},
{
"id":"5678",
"studentName":"Jeck"
}
]
}
]
It seems like you want to merge the objects to make one unified object of custom type, here is what you want to do:
res => resolve(
{
...res[1].value[0],
...res[0].value[0],
Students: res[2].value
}
)
The ... is called spread syntax. It "explodes" the objects and arrays. What we want here is get the internals of classRooms.value[0] merge them with school.value[0] object's internals, and then, add another attribute at the same level with key as Students which is a not-exploded array specified by student.value.
Here I have created a small TS Playground Example for you to play with the syntax and modify the output the way you may seem fit.
If you run it, it prints the desired output:
{
"class_id": "171717",
"teacher_name": "Science",
"id": "2345354",
"schoolName": "Memorial High School",
"Students": [
{
"id": "1234",
"studentName": "Beck"
},
{
"id": "5678",
"studentName": "Jeck"
}
]
}
-- ORIGINAL ANSWER --
Promise.all returns a promise of resolved objects in an array. So, the .then takes the parameter that's an array of resolved objects in the same order. That means your res parameter is an array of school object, students object, and classroom object in that order. you can do the following to "zip" them up.
new Promise((resolve, reject) => {
const school = getschool (webHost, dataSource, req);
const classRooms = getClassRooms(webHost, dataSource, req);
const students = getstudents (webHost,dataSource, req);
Promise.all([school ,classRooms,students ]).then((res) => {
resolve({"schools": res[0], "classRooms" : res[1], "students": res[2]});
})
.catch((error) => {
logger.error(`${error}`);
reject(error);
});
});
or even better,
.then(([schools, classRooms, students]) => {
resolve({schools, classRooms, students});
})

How can I push an object to a nested array of objects in mongoDB and expressjs

I have the following Board object:
{
"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
}
as you can see there is a "boardLists" array, I want to make a post request that post a card to a list inside that array with specific ID.
that my code:
router.post("/add-task/:id", auth, boardAuth, async (req, res) => {
const listId = req.params.id;
try {
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.updateOne(
{ _id: req.board._id, "boardLists._id": listId },
{ $push: { "boardLists.$.cards": task } }
);
await board.save();
res.send(board);
} catch (err) {
console.log(err);
}
});
Now the problem is when I make the request call in postman its does the push inside the specific list that i want but its not saving the push inside the parent board object: when do a get request to that object i get an empty cards array.
like that:
{
"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
}
Why its not saving the push in the board object?
Mongoose is weird. You need to mark the field as modified, otherwise the changes won't be saved. Try this :
board.markModified("boardLists");
await board.save();

Resources