GraphQL - search string in multiple fields - graphql

I am trying to search for a string across multiple fields with GraphQL.
I was able to use filter function with an or field, but it was not retrieving anything.
I want to be able to retrieve an array with all the items that contain the searched string in title or/and body ==> so if the query string was found in title or body retrieve it to array.
My code is:
const search_reviews= gql`
query SearchReviews ($my_query: String) {
reviews (filters: {title: {contains: $my_query}, or: {body: {contains: $my_query}} }) {
data{
id
attributes{
title
rating
body
categories{
data{
id
attributes
{
name
}
}
}
}
}
}
}
`
Works ok with only one field, but I want to have it in both fields
const search_reviews= gql`
query SearchReviews ($my_query: String!) {
reviews (filters: {body: {contains: $my_query} }) {
data{
id
attributes{
title
rating
body
categories{
data{
id
attributes
{
name
}
}
}
}
}
}
}
`

Seems that they changed the API.
Here is some code:
const search_reviews = gql`
query SearchReviews ($my_query: String!) {
reviews (filters: {or: [{body: {contains: $my_query} }, {title: {contains: $my_query}}]}) {
data{
id
attributes{
title
rating
body
categories{
data{
id
attributes
{
name
}
}
}
}
}
}
}
`
Basically you need to use $filters with an or to search in body or in the tile.
reviews (filters: {or: [{body: {contains: $my_query} }, {title: {contains: $my_query}}]})
Cheers to all!

Related

How to pass variables to strapi graphql api?

I have the following graphql code in my strapi and nextjs project. The code is working in the graphql end point playground but some how it keeps getting error in my local environment showing message: 'Syntax Error: Expected Name, found <EOF>.', when I try to fetch data from nextjs. I have ready this strapi documentation but cant seems to find anything relevant with my current issues. Any can please tell me what error I am making here?
export async function getPostAndMorePosts(slug, preview) {
const data = await fetchAPI(
`
fragment FileParts on UploadFileEntityResponse {
data {
id
attributes {
alternativeText
width
height
mime
url
formats
}
}
}
query Posts($slug: String!) {
posts(filters: {slug: {eq: $slug}}) {
data{
attributes{
title
content
excerpt
slug
category{
data{
attributes{
name
}
}
}
coverImage{
...FileParts
}
}
}
}
morePost: posts(filters: {slug: {ne: $slug}},pagination: { start: 0, limit: 4 }) {
data{
attributes{
title
content
excerpt
slug
category{
data{
attributes{
name
}
}
}
coverImage{
...FileParts
}
publishedAt
}
}
}
}`,
{variables:{
slug:slug
}
}
)
return data
}
Your code needs a closing bracket which is misaligned at the moment! Look at the code below
export async function getPostAndMorePosts(slug, preview) {
const data = await fetchAPI(
`
fragment FileParts on UploadFileEntityResponse {
data {
id
attributes {
alternativeText
width
height
mime
url
formats
}
}
}
} -> closed here
query Posts($slug: String!) {
posts(filters: {slug: {eq: $slug}}) {
data{
attributes{
title
content
excerpt
slug
category{
data{
attributes{
name
}
}
}
coverImage{
...FileParts
}
}
}
}
morePost: posts(filters: {slug: {ne: $slug}},pagination: { start: 0, limit: 4 }) {
data{
attributes{
title
content
excerpt
slug
category{
data{
attributes{
name
}
}
}
coverImage{
...FileParts
}
publishedAt
}
}
}
`, -> removed from here
{variables:{
slug:slug
}
}
)
return data
}
So it's just an issue of {} alligment.

GraphQL filtering/sorting DatoCMS GatsbyJS

I have the following GraphQL query:
export const query = graphql`
query NewsQuery($slug: String!) {
datoCmsNews(slug: { eq: $slug }) {
id
title
description
slug
meta {
publishedAt
}
cover {
fluid(maxHeight: 530) {
...GatsbyDatoCmsSizes
}
}
}
allDatoCmsNews(sort: { fields: [meta___publishedAt], order: DESC }, limit: 4) {
edges {
node {
id
title
slug
meta {
publishedAt
isValid
status
}
cover {
fluid(maxHeight: 375) {
...GatsbyDatoCmsSizes
}
}
}
}
}
}
`;
On my allDatoCmsNews query how would I go about about sorting/filtering out a News item where a $slug is equal to the current slug? I don't want to show a News item if that news item is currently being viewed. I'm guessing I would have to use neq just struggling with the correct syntax.
Thanks
Pretty trivial using filter:
allDatoCmsNews(sort: { fields: [meta___publishedAt], order: DESC }, limit: 4, filter: {slug: {ne: $slug}})

How to work around GraphQL error, field "x" must not have a selection since type "String" has no subfields

I am using Gatsby and GraphQL, and I am new to GraphQL.
I have the following schema definition:
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions;
const typeDefs = `
type MarkdownRemark implements Node {
frontmatter: Frontmatter
}
type Frontmatter {
title: String!
products: [Product]
}
type Product #dontInfer {
name: String!
price(price: Int = 1): Float
description: String
images: [ProductImage]
}
type ProductImage {
url: String
}
`;
createTypes(typeDefs);
};
Then on my page I use the following query:
query {
markdownRemark(fileRelativePath: { eq: "/content/pages/products.md" }) {
...TinaRemark
frontmatter {
title
products {
name
price
description
images {
url {
childImageSharp {
fluid(maxWidth: 1920) {
...GatsbyImageSharpFluid_withWebp
}
}
}
}
}
}
html
}
}
I then receive the following error:
Field "url" must not have a selection since type "String" has no subfields.
Does anyone have any suggestions on how to work around this error?
Also, what is childImageSharp? I'm wondering what the terminology is to define it. Is it a GraphQL "selector" or "function"?
It should be
query {
markdownRemark(fileRelativePath: { eq: "/content/pages/products.md" }) {
...TinaRemark
frontmatter {
title
products {
name
price
description
images {
url
}
}
}
html
}
}
Because you definition is
type ProductImage {
url: String
}
The url apparently has no sub fields.
For what it's worth (I don't know if this is related to your specific issue.) If your markdown path for the image file is invalid, GraphQL will return this error, interpreting the path as a string. I had this problem and it went away when I realized I had misspelled the path in the markdown.
productImage {
childImageSharp {
gatsbyImageData(width: 200)
}
}
I had a similar problem with returning a boolean. For me, instead of something like this
mutation {
someFunc(
memo: "test memo"
) {
success
}
}
I needed this
mutation {
someFunc(
memo: "test memo"
)
}

Get other related records (with id different that queried)

As a newbie to GraphQL I would appreciate some help in the following:
I have query which retrieves its author and that author's books. I would like the author's books to be author's other books, meaning - except the one being queried. What does it involve?
apollo-angular query:
const getBookQuery = gql`
query($id: ID){
book(id: $id){
id
name
year
author {
id
firstName
lastName
books { # <-- give me all _except_ the one with $id
name
year
id
}
}
}
}
`;
and in the schema.js (node.js server) I have something like:
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
const { id } = args;
return Book.findById(id);
},
},
books: {
type: GraphQLList(BookType),
resolve() {
return Book.find({});
},
},
// ... other queries ...
}
})
The solution I am looking for should, obviously, not break other queries for books.
You should be able to achieve the exclusion by adding an argument to the Author type def and then appropriately using that argument in the resolver for books (which should be nested resolver on your Author type). Will need to adapt syntax for apollo-angular.
type Author {
id:
firstName: String
lastName: String
books(exclude: ID): [Book]
}
const resolverMap = {
Query: {
book(arent, args, ctx, info) {
...
}
},
Author: {
books(obj, args, ctx, info) {
// Use args.exclude passed to filter results
},
},
};
const getBookQuery = gql`
query($id: ID){
book(id: $id){
id
name
year
author {
id
firstName
lastName
books(exclude: $id) {
name
year
id
}
}
}
}
`;

graphql, split huge query to small queries

I am using https://developer.github.com/v4/
And I have a huge query like this:
query ($login: String!, $first: Int, $after: String) {
user (login: $login){
avatarUrl
login
name,
followers(first: $first, after:$after) {
edges{
cursor
node{
id
name
login
avatarUrl
}
}
totalCount
},
repositories(first: $first) {
edges{
cursor
node{
id
name
}
}
totalCount
}
}
}
But I think it's bad to query huge data from server.
I have followers and repositories pages. So I think split this huge query to small queries is better.
Here is small queries:
followers query:
query($login: String!, $first: Int, $after: String) {
user(login: $login) {
followers(first: $first, after: $after) {
edges {
cursor
node {
id
name
login
avatarUrl
}
}
totalCount
}
}
}
repositories query:
query($login: String!, $first: Int, $after: String) {
user(login: $login) {
repositories(first: $first, after: $after) {
nodes {
id
name
}
totalCount
}
}
}
user query:
query($login: String!, $first: Int) {
user(login: $login) {
avatarUrl
login
name
}
}
Am I correctly? Is it necessary to do this? What's the best practice this situation? Is there any documentation for teaching people how to handle this or told people the best practice?
You can spit your queries into Fragments and in that way you would still only trigger one request and have smaller "queries". Something like this:
Fragment for followers:
fragment followers on User {
followers(first: $first, after: $after) {
edges{
cursor
node{
id
name
login
avatarUrl
}
}
totalCount
},
}
Fragment for repositories:
fragment repositories on User {
repositories(first: $first) {
edges{
cursor
node{
id
name
}
}
totalCount
}
}
Put them all together in the query:
query ($login: String!, $first: Int, $after: String) {
user (login: $login){
avatarUrl
login
name
...followers
...repositories
}
}

Resources