Strapi, use find to check if an object type field has a match in one of the properties - strapi

Let's say I have a field called user with a data that looks something like this
{
"id": "abc123",
"name": "John Smith"
}
I want to make a route where I can find where user.id equals, say, abc123 and should return the blogs that has a user with the id above
I've tried doing
async findByUser(ctx) {
let blogs = await strapi.services.blogs.find({
user: {id:ctx.params.id},
return blogs;
},
but that doesn't seem to work as it returns an empty array and isn't searching specifically in the id property. How do I do this using strapi?
edit: User is not an relation, it is an individual JSON field.

Okay, for querying a JSON object property, you will need to write a custom query. Look at the example below.
Implementation for PostGreSQL
async findByUser(ctx) {
const response = await strapi
.query('blogs')
.model.query((qb) => {
qb.where('user', '#>', `{"id": "${ctx.params.id}" }`);
// qb.where('user', '#>', `{"name": "${ctx.params.name}" }`);
})
.fetch();
return response.toJSON();
},
Implementation for SQLite
async findByUser(ctx) {
const response = await strapi
.query('blogs')
.model.query((qb) => {
qb.where('user', 'LIKE', `%"id":"${ctx.params.id}"%`);
})
.fetch();
return response.toJSON();
},
P.S: Just use fetch instead of fetchAll for consistency.

Hi there thanks to Salvino's help I think i am able to find a solution
async findByUser(ctx) {
const response = await strapi
.query('blogs')
.model.query((qb) => {
qb.where('user', 'LIKE', `%"id":"${ctx.params.id}"%`);
})
.fetchAll();
return response.toJSON();
},

Related

AppSync pipeline resolver for appending data to each item within a list

Can someone help me create a resolver that adds data from another documentDB collection to each item within the query response list?
Given the grossly overly simplified following schema:
type Asset {
id: ID!
...
}
type DeviceData {
id: ID!
assetID: string
asset: Asset
...
}
Query {
findDevicesQuery: [DeviceData]
}
for example:
findDevicesQuery() => currently returns all devices
I now need to get the associated asset for each device by assetID and then append it to the findDevicesQuery response for each device
ie:
findDevicesQuery => returns
[
{deviceData1, associatedAssetData1},
{deviceData2, associatedAssetData2},
{deviceData3, associatedAssetData3}
]
I would've done this with a connection in Amplify using DynamoBD, however this project is not using Amplify and it is using documentDB.
As always, any and all direction is appreciated, so thanks in advance!
I took a different approach, so adding it here for anyone else who might stumble here...
Since mongoDB (AWS DocumentDB) is used, an aggregation api is exposed, so I used it:
MongoModel.aggregate([
{
$lookup: {
from: 'assets',
localField: 'assets_id',
foreignField: '_id',
as: 'asset'
}
}
])
.limit(10)
.then(data => {
console.log('findDevicesQuery() data', JSON.stringify(data))
resolve(data)
})
.catch(error => reject(new Error(`${ERROR_FINDING_DEVICES}: ${error}`)))```

Strapi GraphQL search by multiple attributes

I've got a very simple Nuxt app with Strapi GraphQL backend that I'm trying to use and learn more about GraphQL in the process.
One of my last features is to implement a search feature where a user enters a search query, and Strapi/GraphQL performs that search based on attributes such as image name and tag names that are associated with that image. I've been reading the Strapi documentation and there's a segment about performing a search.
So in my schema.graphql, I've added this line:
type Query {
...other generated queries
searchImages(searchQuery: String): [Image
}
Then in the /api/image/config/schema.graphql.js file, I've added this:
module.exports = {
query: `
searchImages(searchQuery: String): [Image]
`,
resolver: {
Query: {
searchImages: {
resolverOf: 'Image.find',
async resolver(_, { searchQuery }) {
if (searchQuery) {
const params = {
name_contains: searchQuery,
// tags_contains: searchQuery,
// location_contains: searchQuery,
}
const searchResults = await strapi.services.image.search(params);
console.log('searchResults: ', searchResults);
return searchResults;
}
}
}
},
},
};
At this point I'm just trying to return results in the GraphQL playground, however when I run something simple in the Playground like:
query($searchQuery: String!) {
searchImages(searchQuery:$searchQuery) {
id
name
}
}
I get the error: "TypeError: Cannot read property 'split' of undefined".
Any ideas what might be going on here?
UPDATE:
For now, I'm using deep filtering instead of the search like so:
query($searchQuery: String) {
images(
where: {
tags: { title_contains: $searchQuery }
name_contains: $searchQuery
}
) {
id
name
slug
src {
url
formats
}
}
}
This is not ideal because it's not an OR/WHERE operator, meaning it's not searching by tag title or image name. It seems to only hit the first where. Ideally I would like to use Strapi's search service.
I actually ran into this problem not to recently and took a different solution.
the where condition can be combined with using either _and or _or. as seen below.
_or
articles(where: {
_or: [
{ content_contains: $dataContains },
{ description_contains: $dataContains }
]})
_and
(where: {
_and: [
{slug_contains: $categoriesContains}
]})
Additionally, these operators can be combined given that where in this instance is an object.
For your solution I would presume you want an or condition in your where filter predicate like below
images(where: {
_or: [
{ title_contains: $searchQuery },
{ name_contains: $searchQuery }
]})
Lastly, you can perform a query that filters by a predicate by creating an event schema and adding the #search directive as seen here

Multiple graphql queries in Gatsby component

I need to run multiple graphQL queries within a component and within the gatsby-node.js file. (Because Prismic is limited to 20 entries per answer...🙄)
I tried the following, just to see if I could create the graphql loop in the default function:
export default () => {
async function allPosts() {
let data
await graphql(`
query allDitherImages {
prismic {
allProjects(sortBy: meta_firstPublicationDate_DESC) {
totalCount
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
edges {
node {
cover_image
cover_imageSharp {
name
}
}
}
}
}
}
`).then(initialRes => {
data = initialRes
})
return data
}
allPosts().then(result => {
console.log(result)
})
return null
}
But then Gatsby tells me that Gatsby related 'graphql' calls are supposed to only be evaluated at compile time, and then compiled away. Unfortunately, something went wrong and the query was left in the compiled code.
How can I run multiple graphql queries?
Thank you in advance :)
Michael
The gatsby-source-prismic-graphql package will create pages for all of your Prismic items (more than just the first 20), as it iterates over all items under the hood, so I'd advise looking into using that if you are looking to generate pages for all of those items.
But if you need to get all items and pass them in the pageContext or something, you'll need to do the recursion yourself in the gatsby-node.
In the gatsby-node, after you have defined the query, you can use something like this to iterate over the results and push to an array.
let documents = [];
async function getAllDocumentsRecursively (query, prop, endCursor = '') {
const results = await graphql(query, { after: endCursor })
const hasNextPage = results.data.prismic[prop].pageInfo.hasNextPage
endCursor = results.data.prismic[prop].pageInfo.endCursor
results.data.prismic[prop].edges.forEach(({node}) => {
documents.push(node)
});
if (hasNextPage) {
await getAllDocumentsRecursively(query, 'allDitherImages ', endCursor)
}
}
await getAllDocumentsRecursively(documentsQuery, 'allDitherImages ');
Then in your createPage, pass the array into the context:
createPage({
path: `/`+ node._meta.uid,
component: allDitherTempate,
context: {
documents: documents
}
})

GraphQL Filter on Enum Column

Below is my GraphQL Query to Fetch Posts from Strapi backend.
Please note I am running this on my Nuxt app.
Now I want to bring only those posts which have post_status = "Publish"
post_status is a ENUM field with two option as Draft and Publish
query GetPosts{
posts {
id
post_title
post_excerpt
post_featured_image{url}
post_content
post_category{category_name}
postingredients{ingredient{ingredient_name}, ingredient_unit}
updated_at
post_author{username}
post_slug
}
}
I did not understand how can I get
How to bring post_status values on my original Query
How to filter on the post_status where I can get only Published posts.
query GetStatusEnum{
__type(name: "ENUM_POST_POST_STATUS") {
name
enumValues {
name
} } }
Result of the above:
{
"data": {
"__type": {
"name": "ENUM_POST_POST_STATUS",
"enumValues": [
{
"name": "Publish"
},
{
"name": "Draft"
}
]
}
}
}
To add your post_status in your original request you just have to add it in the list of the attributes you want to fetch.
{
posts {
id
post_title
post_status <- here /!\
}
}
Here is the query to fetch Posts that have Publish as post_status
{
posts(where: { post_status: "Publish" }) {
id
post_title,
post_status
}
}
You can play with GraphQL playground in your strapi application:
http://localhost:1337/graphql
You will see in the right of you page a docs button that will show you all the information you need to create your GraphQL request.
I had a similar scenario (though I'm using a Prisma layer as well so keep that in mind) and i'm not sure that you can filter for enum values on the call but you can filter what it returns.
const posts = [the array of all posts]
const isPublished = (post) => {
if (post.post_status.includes('Publish')) {
return post;
}
}
let publishedPosts = posts.filter(isPublished);
return publishedPosts;

Limit Graphql results that belongs to owner in Strapi

I am using a simple Strapi policy like below to limit the REST result that belongs to the owner only, which documented in the following link.
https://github.com/strapi/strapi/issues/624
module.exports = async (ctx, next) => {
const { id, role } = ctx.state.user;
if(role !== 'administrator'){
ctx.query.owner = id;
}
await next();
};
Now I want to do the same for Graphql results, but it doesn't seems to work with the same code because "ctx.query" is undefined. I have tried looking at the all the request API but none of them seems to be work for Graphql query. The URL ended like 'http://localhost:1337/graphql', and 'ctx.request.query' is an empty [].
https://strapi.io/documentation/3.0.0-beta.x/guides/requests.html#api-reference
Here what I did to solve that problem:
Override the GraphQl Schema in api/activity/config/schema.graphql
module.exports = {
definition: ``,
query: `
notifications(sort: String, limit: Int, start: Int, where: JSON): [Activity]
`,
type: {},
resolver: {
Query: {
notifications: {
description: 'Return the auth user notifications',
policies: ['plugins.users-permissions.permissions'],
resolver: 'Activity.findNotifications'
},
},
},
};
Create a new function resolver in api/activity/controllers/Activity.js
module.exports = {
findNotifications(ctx) {
ctx.query = { ...ctx.query, owner: ctx.state.user.id }
if (ctx.query._q) {
return strapi.services.activity.search(ctx.query);
}
return strapi.services.activity.find(ctx.query);
},
}
In the controller you got the query and add the owner id filter.
Hope it helps.
Why are you looking at REST docs while searching for graphQL problem? There is no url query parsing at all.
Owner role (permissions) can be checked using policies - it's described here.
The following sections contain examples of misc permission/customization - resolvers have a context parameter. User data should (did't checked) be available at context.state.user.

Resources