How to search items in AWS Amplify Datastore? - amazon-web-services

In my react native app with AWS amplify backend I want to search 'product' model.
At the moment I'm doing it like this first I query all the products like this
useEffect(() => {
const getallProducts = async () => {
await DataStore.query(Product).then(setAllProducts);
};
getallProducts();
}, []);
Then I filter these products to show the search results to the User.
But I want to implement this search function without querying all products to the device. How can I do this?

Related

Is it safe to expose AWS Amplify like this?

In my react native app I use Amplify Datastore to query,create and update items. I want to know is it safe to expose these methods in my frontend ? and can someone reverse engineer and use these ? and what can I do to increase the security of these methods ?
const getOrder = async () => {
await DataStore.query(Order, c=>c.iD.eq(currentOrderId)
}
const createOrder = async () => {
await Datastore.save(new Order({
// }))
}
etc

Next.js SSR with AWS Amplify Why is User Needed to View Data?

I'm working with Next.js Server Side Rendering and AWS Amplify to get data. However, I've come to a roadblock, where I'm getting an error saying that there's no current user.
My question is why does the app need to have a user if the data is supposed to be read for the public?
What I'm trying to do is show data for the public, if they go to a user's profile page. They don't have to be signed into the app.
My current folder structure is:
/pages/[user]/index.js with getStaticProps and getStaticPaths:
export async function getStaticPaths() {
const SSR = withSSRContext();
const { data } = await SSR.API.graphql({ query: listUsers });
const paths = data.listUsers.items.map((user) => ({
params: { user: user.username },
}));
return {
fallback: true,
paths,
};
}
export async function getStaticProps({ params }) {
const SSR = withSSRContext();
const { data } = await SSR.API.graphql({
query: postsByUsername,
variables: {
username: params.username,
},
});
return {
props: {
posts: data.postsByUsername.items,
},
};
}
Finally figured it out. A lot of tutorials uses authMode: 'AMAZON_COGNITO_USER_POOLS ' // or AWS_IAM parameter in their graphql query for example in https://docs.amplify.aws/lib/graphqlapi/authz/q/platform/js/
// Creating a post is restricted to IAM
const createdTodo = await API.graphql({
query: queries.createTodo,
variables: {input: todoDetails},
authMode: 'AWS_IAM'
});
But you rarely come across people who use authMode: API_KEY.
So I guess, if you want the public to read without authentication, you would just need to set authMode: 'API_KEY'...
Make sure you configure your amplify API to have public key as well.

aws xray not monitoring dynamo dax client in nodejs

I recently started using dynamodb dax within my node lambda function, however with 'amazon-dax-client' framework, i cannot longer capture transparently with http requests made by the framework, like so;
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
const dynamoDB = AWSXRay.captureAWSClient(new AWS.DynamoDB(defaults.db.config));
I know i could create an async capture. but i am wondering if there is a better way to do this, like in the previous way and if i someone managed to capture requests, made with dax-client in the same way as with the dynamo client from aws framework.
DAX doesn't currently support XRay, because DAX doesn't use the standard AWS SDK HTTP client (it doesn't use HTTP at all).
The team has received other requests for XRay support so it's certainly something we're considering.
While there is no official support for XRAY from DAX team. I wrote a little snippet as a workaround.
const db = new Proxy(documentClient, {
get: (target: any, prop: any) => {
if (typeof target[prop] === "function") {
return (...args: any) => {
const segment = xray
.getSegment()
?.addNewSubsegment(`DynamoDB::${prop}`);
const request = target[prop](...args);
const promise = request
.promise()
.then((response: any) => {
segment?.close();
return response;
})
.catch((err: any) => {
segment?.close();
return Promise.reject(err);
});
return {
...request,
promise: () => promise,
};
};
}
return target[prop];
},
});
const response await = db.query(...).promise();
Tested in AWS Lambda under VPC private subnet and AWS XRAY service endpoint.

Continuous data update via pouchdb query

i have a pouchdb database with a number of views setup that i query whenever i need data. I am using observables to handle the querying. However i have to refresh the interface to view any data changes in the database. Is there any way i can have these data changes read directly by the observable ? My code is as:-
home.ts
this.postsService.getPosts().subscribe((posts) => {
this.posts = posts.rows.map(row => {
console.log(row.value);
return row.value;
});
});
posts.ts
getPosts(): Observable<any> {
return Observable.fromPromise(this.db.query('app/inputs'));
}
You can use use db.changes with your view, so that you'll only get events for view related changes:
db.changes({
filter: '_view',
view: 'app/inputs',
live: true,
since: 'now',
include_docs:true
}).on('change', (change) => { this.handleChange(change); });
See the filtered changes section on PouchDB docs for a more detailed explanation on this.

How do I refetch a query outside of its wrapped component?

I have two screens:
Screen1: Results
Screen2: Edit Filters
When I edit the filters on Screen2 and press back, I would like to refetch the query on Screen1 (with the newly built filter string variable). Editing the filters doesn't use a mutation or fire any Redux actions (I'm storing the users search filters/preferences in localStorage/AsyncStorage instead of a database, so no mutation). I'm merely changing the local state of the form and use that to build a filter string that I want to pass to a certain query on Screen1. I have access to the filter string on both screens if that helps.
It seems like refetch() is limited to the component its query wraps http://dev.apollodata.com/react/receiving-updates.html#Refetch so how would I re-run the query from a different screen?
I tried putting the same query on both Screen1 and Screen2, then calling the refetch on Screen2, and although the query works and gets the new data on Screen2, the same name query doesn't update on Screen1 where I actually need it. Isn't it supposed to if they have the same name? (but the filters variable changed)
If I am just designing this incorrectly and there is an easier way to do it, please let me know. I expect that if I have 2 screens, put the same query on both of them, and refetch one of the queries with a new filters variable, then the refetch should happen in both places, but it's currently treating them individually.
I did the same thing here. The scenario:
- I choose a peer to filter some messages.
- I keep the peerId into redux
- I make both components (the filter and the list) dependent on that redux value.
Like this:
1 - To put that filter value on redux (and to grab it back):
import { compose, graphql } from 'react-apollo'
import { connect } from 'react-redux';
...
export default compose(
connect(
(state,ownProps) => ({
selectedMessages: state.messages.selectedMessages,
peerId: state.messages.peerId
}),
(dispatch) => ({
clearSelection: () => dispatch(clearSelection()),
setPeer: (peerId) => dispatch(setPeer(peerId))
})
),
graphql(
PEERS_QUERY,
...
when you call connect first (using compose), before you call a graphql wrapper, or outside that wrapper, you will have peerId available as a prop on your graphql wrapper, so you can use it to filter your query:
export default compose(
connect(
(state,ownProps) => {
return {
peerId: state.messages.peerId,
selectedMessages: state.messages.selectedMessages
}
},
(dispatch) => ({
toggleMessage(messageId) {
dispatch(toggleMessage(messageId));
}
})
),
graphql( // peerId is available here because this is wrapped by connect
MESSAGES_QUERY,
{
options: ({peerId}) => ({variables:{peerId:peerId}}),
skip: (ownProps) => ownProps.peerId === '',
props: ({
...
...
...
)(MessageList);