I am trying to perform a query using the in operator where the criteria is based on values in an array. How can I perform the query below to take an array and base its in criteria off a variable array? I am using reactjs + gatsby.
... graphql`
query pageHeader {
.... there is another query in the real code above this line
allContentInSites (filter: {slug: {in: ` + JSON.stringify(searchCriteria.map(item => item.value)) + ` }}) {
edges {
node {
title,
link
}
}
}
}'
I was initially thinking the sample code above would pass a json string object for the in criteria but this seems to break the page.
This won't work in your page queries in Gatsby. The GraphQL query is evaluated and replaced with data statically prior to the code being executed.
You could potentially hook into the Node APIs provided by Gatsby to build this query during boot, though. You may be able to use onPreExtractQueries to create the query, or potentially use the graphql object provided by any of the node APIs in your gatsby-node.js to generate pages.
if you would like to implement dynamic filtering criteria, you have couple options
1) You can use stringified json and send it as String and parse it on the server in resolver
2) You can use custom scalar graphql-type-json as argument type or implement your own custom scalar.
The big downsides of this is that you are loosing strongly typed features of GraphQL. You can also implement dynamic schema, but it is a little bit overkill and in general not a good practice. I would go for dynamic arguments only if it is the only option. Usually it can be rearanged so that you do not have to use dynamic arguments.
I am not sure if it is helpful as i am not familiar with gatsby specific issues with this, but this should work in general GraphQL schemas.
Related
I want to build a search page that lets user query data based on certain criteria that they can choose from select and radio checkboxes, on behalf of which a query string is generated that gives the key/value pair for searching, the functionality is somewhat similar to what they have for their staters page.
Please check the link below to get an idea of what I am looking for:
https://www.gatsbyjs.org/starters/?v=2 <---- query string.
These pages need to be shareable so query strings are essential and data fetching need be as quick as it is on their website.
From what I have understood so far, according to documentation:
https://www.gatsbyjs.org/docs/data-fetching
I have two options:
Get data during build time
Get data during run time
For a run time, I think, I would need to use redux-thunk to make network calls to an ExpressJs, MongoDB REST API but my concern is that it can be slow.
For build time, I am sure on how can I source data from Graphql queries, and render them.
Any help on this will be great. Thanks
The Gatsby Starters Library is parsing the URL param in this urlToSearch method in the PluginSearchBar component:
urlToSearch = () => {
if (this.props.location.search) { // get the params from the location prop
const match = /(\?|&)=([^&]+)/.exec(this.props.location.search)
if (match) return decodeURIComponent(match[2])
return ``
}
return ``
}
Mainly, it uses the Gatsby location prop (from #reach/router under the hood) to get the search keyword from the query string.
Search is then implemented client-side using Algolia's react-instantsearch library. You can find the complete implementation in plugin-searchbar-body.js.
There are naturally other ways to implement search. A good place to start for inspiration is Gatsby's Adding Search documentation.
Hey i'm using Sanity and have created both a allSanityPost (for my blog posts) and allSanityCases (for all my cases). Do anyone know how to combine these categories into one array and order them by their "published-date"? I want to display them both on one blog page - but not in separated lists.
I'm building the page with Gatsby, so react answers would be preferable :)
Cheers
The current GraphQL endpoint have no way of querying across documents like GROQ does. Therefore, you will have to do this after querying the GraphQL endpoint for data. I suggest querying for both all posts and all cases separately like this:
query {
allSanityPost{
title
},
allSanityCases{
title
}
}
Given that both of these types have some sort of date, you should be able to combine them into one single array, and then do your sorting thereafter.
I am looking for help regarding best practice using Apollo, React and Meteor.
I linked the Meteor.user() model to a Schema in Apollo and I can now access it thanks to a Query Component. I have a query that looks like this :
gql`
query User {
user {
_id,
email
}
}
`
and it does the job, with a resolver giving directly the email adress. However I need it in different places and for every component where I need it I am making another < Query > component with the same Query I copy paste from on file to another. It seems to me that I am loosing the all point if many of my components are querying again and again the same things. However I do not manage to find the solution to this "DRY" problem. There are not yet so many examples including the Query component from react apollo so if someone could help me with this it'd be much appreciated.
By default, the Apollo client uses a fetchPolicy of cache-first. That means if the result of the query is already in the cache, it will be fetched from there and no network request will be made. That allows you to use the same query across multiple Query components without having to worry about making the same request to your server over and over again.
You can specify the fetchPolicy for a particular Query component if you want to override this default behavior -- for example, maybe you want to always fetch new data from the server, in which case you would use network-only or maybe cache-and-network. See the docs for more details.
NOTE: A common "gotcha" is that the cache uses the id (or _id) field to normalize the cached results. That means your queries have to include the id field (or provide a custom implementation of dataIdFromObject) to see the expected behavior. See this page for additional details.
In terms of keeping things dry, it's common practice to store your queries in one or more separate modules and then import them as needed. So you could have a queries.js file like this:
import gql from 'graphql-tag'
export const USER_QUERY = gql`
query User {
user {
_id,
email
}
}
`
graphql-tag comes with a loader that lets you import queries directly from .graphql/.gql files if you're using Webpack. Check out the recipe here. There's also a babel plugin for doing effectively the same thing (checkout it out here). Any of these approaches should reduce the redundancy in your code.
EDIT: As pointed out in #camba1's answer, fragments can also be used to DRY up your queries:
query User {
user {
...userFields
}
}
fragment userFields on User {
_id,
email,
}
Another thing that may be useful to avoid having to copy paste query code all over the place is to use query fragments .
for example:
# Query that contains a fragment
query myQuery1($_key: ID!) {
myQuery1(_key: $_key) {
field1,
...myFragmentFields
}
}
# Fragment to be used in queries
fragment myFragmentFields on myQueryType {
_key,
name,
formula,
type
}
Here is the documentation:
You can use cache-only or cache-first policy in query.
Docs
Specifically I feel like I am looking for the answer to the question asked here, but it turns out the title of the question isn't a perfect match for the actual question.
What I am looking to do involves Relay, React, and GraphQL (I suppose I could have stated Relay, and you could have figured out the other two).
What I want to do, and what I can't seem to find an answer to, is to create a query that lists a variable list of query fragments based on some predefined JSON array.
If you look at my home page, jimmyvanveen.com you will see I have a list of projects I have worked on (or am working on), and each renders as a React component. I am pulling this data from Github through their REST API (v3) - but now I want to migrate to GraphQL (v4).
I can make an array containing the repo name, and owner as required by the Schema of Github's API, but I don't know how to dynamically create a query based off a simple array such as:
repos: [
{"name": "repo name", "owner": "Repo Owner"},
{"name": "other repo", "ownder": "Other Owner"}
]
I know how to make a query that can find all of this information manually, but I was hoping there was a GraphQL way (perhaps by sending vars?) to run through the entire array in one query and return the array of repo data.
I've been racking my brain for days trying to find the answer here, or anywhere, and I'm striking out.
Thanks in advance for any help you can provide!
So, in the end I figured out I am in general just submitting the wrong information to Github in order to pull Repo info from a curated list.
My objective above is still not possible exactly the way I wanted to solve the problem, however the method mentioned above is very similar to a usable method that DOES work. Simply put, supply Github with an array of unique node ID's, rather than Repo Name and Repo Owner, as I had been trying to do.
This way, you are not trying to use a 2D array, and instead you are using a single array, with an equal amount of specificity as the 2D array.
So formulating an array such as:
const repos = [
'uniqueID1',
'uniqueID2',
'uniqueID3',
...
];
...can then be passed through Relay (I had the QueryRenderer set to run on my App component) like so:
query AppQuery($repos:[ID!]!) {
projects: nodes(ids:$repos){
...projects_projects
}
}
You can obtain the node ID's in multiple ways, but the way I did this was by pulling the repo info one by one in GraphiQL with a query such as this:
query {
repository(owner:"JimmayVV", name:"JimmyVanVeen.com") {
id
}
}
I then consolidated all of these ID's into an array, and passed that through to Relay and got the desired results.
I'm sure there are other ways, perhaps using a simple Node script to formulate the array for you, but this was simple enough for me, that I am happy with it.
I have a Dart application that's getting data from a custom Google endpoint. I'm using discoveryapis_generator to generate the client library. I would like to issue a query like the following:
import endpoints_api.dart as EndpointsApi;
api = new EndpointsApi.MyApi();
api.photos.list(api.Photo.post_id == "post1");
endpoints_api.dart is the client library generated by discoveryapis_generator generate.dart. MyApi is my custom endpoints API, and photos is one of its services. I think Photo is an endpoints model class which has an instance property post_id.
Issuing the request results in an error to the effect that Photo has no static getter "post_id". This is close to how to the syntax of a query in the Python API, so it was the only way I could think of to specify it here.
I don't know what else might be helpful in describing my request. Hopefully it is self-evident. There's an active enhancement described here, but it seems to refer to limiting the fields, rather than items, in the response.
Update:
Poking around in the client library, I found the source for the list methods. It certainly looks like query parameters are supported. But it seems to me that it's not entirely correct. The formal parameter list contains the query parameters specified in the API surrounded by braces:
async.Future<PhotoCollection> list({core.String postId, core.String regionId}) {...
But in the method body, there's the following:
if (regionId != null) {
_queryParams["region_id"] = [regionId];
Are the brackets in [regionId] to extract region from the parameter list?
I pulled the braces out of the parameter list. Since I only ever expect to query by postId, that's the only parameter:
async.Future<PhotoCollection> list(core.String postId) {...
Voila. I can now add a parameter to the query by just specifying its value in the call:
api.photos.list("post1");
If you wrap the parameters of a method in curly braces, you make them optional.
So you can still use your method with the given signature. You just have to add the name of the parameter you want to pass:
api.photos.list(postId: "post1");