I use Apollo Client on my Nuxt projects to query GraphQL endpoints and it works great. But now, I need to query an Elasticsearch endpoint on AWS. How would I query this endpoint using my existing Apollo client?
You should not query the ElasticSearch directly from your Vue component. You should query your ApolloGraph Server that will query your ElasticSearch end point and return the result from that query.
You can query the Elasticsearch from inside your resolver. The ApolloGraphQL resolver accepts an promise as result and will wait for this promise get resolved.
If you have a resolver like this:
const resolvers = {
Query: {
user(parent, args, context, info) {
let bar = args.id;
return queryElasticSearch(bar)
}
}
}
(For reference: https://www.apollographql.com/docs/apollo-server/data/resolvers/)
The ElasticSearch have this client wich you can connect to query your endpoint: https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-usage.html
and in queryElasticSearch you can have something like this:
async function queryElasticSearch(bar){
const result = await client.search({
index: 'my-index',
body: { foo: bar }
})
return result;
}
Related
I have a yoga graphQL server set up in between API Gateway and Lambda
so when making a post call to my-api-gateway.aws.com/graphql, this makes a query and each query is mapped to lambda function
I learned that context is where I can access headers but I'm specifically looking for x-amzn-requestid value which is an unique request id sent from api gateway, but it doesn't seem to exist in context.request.headers or context.req.rawHeaders I could only access x-amzn-trace-id
const resolvers = {
Query: {
hello: async (_, args, context) => {
return {
context: {
request: context.request.headers.get('x-amzn-requestid'),
req2: context.request.headers.get('X-Amzn-Trace-Id'),
req3: context.req.rawHeaders,
req4: Object.keys(context.req),
}}}}
does anyone know where x-amzn-requestid is located inside context argument?
React + Apollo client app. I'm trying to read from my cache using readQuery but can't read the cached fields.
Here's a rundown:
Component SinglePost invokes useQuery which executes my GET_POST query and caches the result. GET_POST query returns type Post!. All is fine, dev tools show that ROOT_QUERY contains a field called getPost with that post.
const { loading, data } = useQuery(GET_POST, {
variables: {
postID,
}
});
SinglePost has a child component DeleteButton that deletes a comment on click. It invokes useMutation and deletes a comment. DELETE_COMMENT query returns type Comment!.
const [deleteComment] = useMutation(DELETE_COMMENT, {
variables: {
postID,
commentID,
},
});
Post has an array of comments, and now I need to update its array in the cache and remove the deleted comment. I use update function within the deleteComment mutation to get the cache object and use readQuery to get the getPost field from it, but it returns null, even though it's there in the dev tools.
update(cache, result) {
const cacheData = cache.readQuery({
query: GET_POST,
});
// code that doesn't run because cacheData is null
}
I suspect when mutating posts via mutations that return a Post type it successfully reads the getPost field, but when mutation queries return a Comment type it can't read getPost in its mutation hook... because there's no reference to a Post type?
For now I'm using refetchQueries as a workaround. I don't like making extra calls to the server, but my smooth brain just can't figure this out. Any help is appreciated.
Whoops, no variables were ever passed to the query.
update(cache, result) {
const cacheData = cache.readQuery({
query: GET_POST,
variables: {
postID
}
});
}
I have a use case where I have apollo-server-express running with a React based apollo-client. I have an external graphql-datasource for some queries. Currently, I've configured apollo-datasource-graphql to be used as a data source for my apollo-server-express. However, this requires duplication of work on the resolver in Apollo as well as the resolver on my external graphql system.
Is there a way for me to pass queries made in the client through the Apollo Server and to the external graphql data source?
Maybe you could access the GraphQL AST from the fourth resolver argument (resolveInfo) and pass it into a GraphQL client?
Here is some prototype code:
import { print } from 'graphql/language/printer';
function forwardOperationResolver(root, args, context, resolveInfo) {
return fetch('https://remote.host/graphql', {
method: 'POST',
body: JSON.stringify({
query: print(resolveInfo.operation),
variables: resolverInfo.variableValues,
}),
})
.then(response => response.json())
.then(response => {
if (response.errors) {
// Handle errors
}
return response.data;
});
}
Downside: This breaks a few things that usually work in GraphQL like partial results and error locations...
Is there a way to configure React Apollo to pass default query string parameters to each query / mutation ?
For now, all my requests have this format :
POST https://domain:8000/graphql;
I would like to have something like :
POST https://domain:8000/graphql?query=queryName
This would help for quick debugging purposes in the Chrome DevTools panel.
You can implement a custom fetch that apollo's http-link will then use.
When instantiating apollo client, do the following:
const customFetch = (uri, options) => {
const { operationName } = JSON.parse(options.body);
return fetch(`${uri}/graph/graphql?opname=${operationName}`, options);
};
const link = createHttpLink({ fetch: customFetch });
I am currently using batching of similar calls on apollo graphql client.
So it sends single call to apollo-server if same graphql query is fired but with different parameters.
But on graphql server side I want to optimize such that there also a single call goes to resolve all graphql queries at once.
Graphql server makes call to api server but for each single batched call, not to resolve all queries at once.
I have used data-loader to use batching but it sends single request only.
genUserInfoDataLoader() {
return new DataLoader(async (arr) => {
logger.info(`---> UserInfoDataLoader Making calls for:${JSON.stringify(arr)}`);
const leagueId = arr[0].split(':')[1];
const UserIds = arr.map(a => a.split(':')[0]);
const userInfoMap = await this.post('endpoint/user-info ', {
userIds: UserIds.join(','),
tourId,
});
return UserIds
.map(
userId => (userInfoMap[userId] ? userInfoMap[userId] : [])
);
});
}