Get db docs with a certain value - node.js

I am trying to get all of the posts that are listed under a group (essentially the topic of a post). Each post document has a field called group_id, which contains the id of the groups document. When I try to search for the posts that contain a specific group_id (given via a link parameter) using the following code, it returns every post in the db, even though they are not listed under the group.
Backend:
const getGroupPosts = async (req, res) => {
const group_id = req.params.id
const posts = await Post.find({group_id}).sort({createdAt: -1})
res.status(200).json(posts)
}
Frontend:
useEffect(() => {
const fetchPosts = async () => {
const response = await fetch(`/api/posts/group/${params.groupId}`, {
headers: {'Authorization': `Bearer ${user.token}`},
})
const json = await response.json()
if (response.ok) {
dispatch({type: 'SET_POSTS', payload: json})
}
}
if (user) {
fetchPosts()
}
}, [dispatch, user])
I am fairly certain that this is an issue with my backend code as I have the same issue when I use postman, although maybe I need to declare another header(?). All help appreciated!

Related

I need to make a request using Prisma that brings selected products by IDs

I have a backend function that returns a request based on an id.
I need it to return me based on an array of ids
If I pass only one ID it works fine, but if I pass more than one, it gives error....
Can someone help?
Thanks
Backend function:
` import prisma from '../../../../libs/prisma'
export default async function handle(req, res) {
const { ids } = req.query
const idsArray = ids.split(',')
const products = await prisma.product.findMany({
where: {
id: {
in: Number(idsArray),
},
},
})
res.json(products)
}`
And Frontend function that passes the parameters on the front is:
const { selectProducts, setSelectProducts } = useContext(ProductContext)
const [productsInfo, setProductsInfo] = useState([])
useEffect(() => {
const uniqIds = [...new Set(selectProducts)]
fetch('/api/products/getAllSelectedProducts?ids=' + uniqIds.join(',')).then((response) => response.json()).then((json) => setProductsInfo(json))
}, [selectProducts])

How to make a GET Request for a unique register with AXIOS and NodeJS/Express

I'm trying to make GET request to external API (Rick and Morty API). The objective is setting a GET request for unique character, for example "Character with id=3". At the moment my endpoint is:
Routes file:
import CharacterController from '../controllers/character_controller'
const routes = app.Router()
routes.get('/:id', new CharacterController().get)
export default routes
Controller file:
async get (req, res) {
try {
const { id } = req.params
const oneChar = await axios.get(`https://rickandmortyapi.com/api/character/${id}`)
const filteredOneChar = oneChar.data.results.map((item) => {
return {
name: item.name,
status: item.status,
species: item.species,
origin: item.origin.name
}
})
console.log(filteredOneChar)
return super.Success(res, { message: 'Successfully GET Char request response', data: filteredOneChar })
} catch (err) {
console.log(err)
}
}
The purpose of map function is to retrieve only specific Character data fields.
But the code above doesn't work. Please let me know any suggestions, thanks!
First of all I don't know why your controller is a class. Revert that and export your function like so:
const axios = require('axios');
// getCharacter is more descriptive than "get" I would suggest naming
// your functions with more descriptive text
exports.getCharacter = async (req, res) => {
Then in your routes file you can easily import it and attach it to your route handler:
const { getCharacter } = require('../controllers/character_controller');
index.get('/:id', getCharacter);
Your routes imports also seem off, why are you creating a new Router from app? You should be calling:
const express = require('express');
const routes = express.Router();
next go back to your controller. Your logic was all off, if you checked the api you would notice that the character/:id endpoint responds with 1 character so .results doesnt exist. The following will give you what you're looking for.
exports.getCharacter = async (req, res) => {
try {
const { id } = req.params;
const oneChar = await axios.get(
`https://rickandmortyapi.com/api/character/${id}`
);
console.log(oneChar.data);
// return name, status, species, and origin keys from oneChar
const { name, status, species, origin } = oneChar.data;
const filteredData = Object.assign({}, { name, status, species, origin });
res.send(filteredData);
} catch (err) {
return res.status(400).json({ message: err.message });
}
};

Shopify REST Admin API - fetch orders by line_items[0].title = something

For context, I am requesting via node-fetch the Shopify Admin REST API orders.json with the queries shown in my code. For some reason, this only returns the latest order regardless of if I add status=any or limit=250 (which is the standard limit for orders). Before I go too much into detail let me show my code so you can understand the query.
const User = require('../models/User.model');
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
const getReportsPartner = async (req, res, next) => {
const user = await User.findById(req.user.id)
const url = 'https://astore.com/admin/orders.json?fields=total_price_usd,line_items';
const headers = {
'X-Shopify-Access-Token': 'anaccesstoken',
'Content-type': 'application/json',
'Authorization': 'anauthkey'
}
fetch(url, { method: 'GET', headers: headers })
.then(res => res.json())
.then(json => {
const orders = json.orders[0]
console.log(orders)
const partner = orders.line_items[0].title
const commission = (orders.total_price_usd * .125).toFixed(2)
res.render('reports/partnerReport', { partner: partner, commission: commission })
})
}
module.exports = { getReportsPartner }
I have attempted modifying the URL in a few ways other than status and limit. I will list some of them below:
https://astore.com/admin/orders.json?fields=total_price_usd,line_items.title=something
https://astore.com/admin/orders.json?fields=total_price_usd,line_items&line_items.title=something
I have also tried line_items[0].title=something in the url as well, however this seems to invalidate the entire request. I appreciate any help you can give. If you need more in terms of context let me know. Ultimately I plan to get recent orders by title and graph the orders and commissions in a report format. For future orders I will be using a webhook, so at the moment I am only worried about past.
As HymnZzy mention in the comments, it is not possible to query for only line_items title. What I have decided to do is make requests for the last 250 orders or from a certain date range. Here is an example url with query.
`https://${yourshop}.com/admin/api/2022-01/orders.json?limit=250&status=any&financial_status=paid&fields=line_items,total_price_usd`
Then I loop through the results and do something with each order with a certain title.
for (let i=0; i<json.orders.length; i++) {
try {
let title = json.orders[i].line_items[0].title
let price = json.orders[i].total_price_usd
/* Do Something with title and price here */
} catch (err) {
console.log(err)
}
}
My only issue is the speed of this method, however it seems Shopify has limited us to something like this if we would like to find orders by line_items title via the REST Admin API.

Pass query from Link to server, first time load query value undefined, after reload get correct query

I try to create some API to external adobe stock.
Like in the title, first time i get query from Link router of undefined, but after reload page it work correctly. My
main page
<Link
href={{
pathname: "/kategoria-zdjec",
query: images.zdjecia_kategoria
}}
as={`/kategoria-zdjec?temat=${images.zdjecia_kategoria}`}
className={classes.button}>
</Link>
and my server
app
.prepare()
.then(() => {
server.get("/kategoria-zdjec", async (req, res) => {
const temat = await req.query.temat;
console.log(temat)
const url = `https://stock.adobe.io/Rest/Media/1/Search/Files?locale=pl_PL&search_parameters[words]=${temat}&search_parameters[limit]=24&search_parameters[offset]=1`;
try {
const fetchData = await fetch(url, {
headers: { ... }
});
const objectAdobeStock = await fetchData.json();
res.json(objectAdobeStock);
const totalObj = await objectAdobeStock.nb_results;
const adobeImages = await objectAdobeStock.files;
} catch (error) {
console.log(error);
}
});
and that looks like getInitialProps on page next page
Zdjecia.getInitialProps = async ({req}) => {
const res = await fetch("/kategoria-zdjec");
const json = await res.json();
return { total: json.nb_results, images: json.files };
}
I think it is problem due asynchronous.
I think this might be due to the fact that you are using fetch which is actually part of the Web API and this action fails when executed on server.
You could either use isomorphic-fetch which keeps fetch API consistent between client and server, or use node-fetch when fetch is called on the server:
Zdjecia.getInitialProps = async ({ req, isServer }) => {
const fetch = isServer ? require('node-fetch') : window.fetch;
const res = await fetch("/kategoria-zdjec");
const json = await res.json();
return { total: json.nb_results, images: json.files };
}
This problem is solved, the issue was in another part of my app, directly in state management, just created new variables, and pass to link state value.

Bot Framework v4 Node.js Location

I'm in the process of designing a chat bot and trying to find some Node.js sample code and/or documentation on how to implement the Azure Maps service as part of Bot Framework V4. There are many examples of how this is accomplished in V3, but there seems to be no examples of a V4 solution for Node.js. I'm looking to create a step in my botbuilder-dialog flow that would launch a simple "where do we ship it too" location dialog that would guide the user through the dialog and store the address results as part of that users profile. Any help or advice on this would be appreciated.
Yes, this is doable. I created a class (probably overkill, but oh well) in which I make my API call, with my supplied parameters, to get the map. I decided to use Azure Maps (vs Bing Maps) only because I was curious in how it differed. There isn't any reason you couldn't do this with Bing Maps, as well.
In the bot, I am using a component dialog because of how I have the rest of my bot designed. When the dialog ends, it will fall off the stack and return to the parent dialog.
In my scenario, the bot presents the user with a couple choices. "Send me a map" generates a map and sends it in an activity to the client/user. Anything else sends the user onward ending the dialog.
You will need to decide how you are getting the user's location. I developed this with Web Chat in mind, so I am getting the geolocation from the browser and returning it to the bot to be used when getMap() is called.
const { ActivityTypes, InputHints } = require('botbuilder');
const fetch = require('node-fetch');
class MapHelper {
async getMap(context, latitude, longitude) {
var requestOptions = {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
redirect: 'follow'
};
const result = await fetch(`https://atlas.microsoft.com/map/static/png?subscription-key=${ process.env.AZURE_MAPS_KEY }&api-version=1.0&layer=basic&zoom=13&center=${ longitude },${ latitude }&language=en-US&pins=default|al.67|la12 3|lc000000||'You!'${ longitude } ${ latitude }&format=png`, requestOptions)
.then(response => response.arrayBuffer())
.then(async result => {
const bufferedData = Buffer.from(result, 'binary');
const base64 = bufferedData.toString('base64');
const reply = { type: ActivityTypes.Message };
const attachment = {
contentType: 'image/png',
contentUrl: `data:image/png;base64,${ base64 }`
};
reply.attachments = [attachment];
await context.sendActivity(reply, null, InputHints.IgnoringInput);
})
.catch(error => {
if (error) throw new Error(error);
});
return result;
};
};
module.exports.MapHelper = MapHelper;
const { ChoicePrompt, ChoiceFactory, ComponentDialog, ListStyle, WaterfallDialog } = require('botbuilder-dialogs');
const { MapHelper } = require('./mapHelper');
const CONFIRM_LOCALE_DIALOG = 'confirmLocaleDialog';
const CHOICE_PROMPT = 'confirmPrompt';
class ConfirmLocaleDialog extends ComponentDialog {
constructor() {
super(CONFIRM_LOCALE_DIALOG);
this.addDialog(new ChoicePrompt(CHOICE_PROMPT))
.addDialog(new WaterfallDialog(CONFIRM_LOCALE_DIALOG, [
this.askLocationStep.bind(this),
this.getMapStep.bind(this)
]));
this.initialDialogId = CONFIRM_LOCALE_DIALOG;
}
async askLocationStep(stepContext) {
const choices = ['Send me a map', "I'll have none of this nonsense!"];
return await stepContext.prompt(CHOICE_PROMPT, {
prompt: 'Good sir, may I pinpoint you on a map?',
choices: ChoiceFactory.toChoices(choices),
style: ListStyle.suggestedAction
});
}
async getMapStep(stepContext) {
const { context, context: { activity } } = stepContext;
const text = activity.text.toLowerCase();
if (text === 'send me a map') {
const { latitude, longitude } = activity.channelData;
const mapHelper = new MapHelper();
await mapHelper.getMap(context, latitude, longitude);
const message = 'Thanks for sharing!';
await stepContext.context.sendActivity(message);
return await stepContext.endDialog();
} else {
await stepContext.context.sendActivity('No map for you!');
return await stepContext.endDialog();
}
}
}
module.exports.ConfirmLocaleDialog = ConfirmLocaleDialog;
module.exports.CONFIRM_LOCALE_DIALOG = CONFIRM_LOCALE_DIALOG;
Hope of help!
---- EDIT ----
Per request, location data can be obtained from the browser using the below method. It is, of course, dependent on the user granting access to location data.
navigator.geolocation.getCurrentPosition( async (position) => {
const { latitude, longitude } = position.coords;
// Do something with the data;
console.log(latitude, longitude)
})

Resources