Not getting count according to filter in GraphQL amplify queries - graphql

Getting Scanned count but not count of data according to filter
count: null
items: [{id: "bcd75096-7fd9-4e9d-8675-6877f0609ac2", name: "dxfrdhjkhklklkl", description: "dgdxrfg",…},…]
0: {id: "bcd75096-7fd9-4e9d-8675-6877f0609ac2", name: "dxfrdhjkhklklkl", description: "dgdxrfg",…}
1: {id: "52f6ff60-fc07-4631-a1fb-b039f376ff21", name: "ghnfgyhj", description: "gyhkjmuhjolk",…}
2: {id: "f73dfb37-2778-4b87-88c7-e6f9f5b5c931", name: "drftgserty", description: "trse54rte54ty",…}
3: {id: "6df9f5c2-ec06-4e70-b5e2-133cb0d8e958", name: "tygujghukuh", description: "tuyjyuikuolnh",…}
4: {id: "9360a766-ac89-420c-881b-2b3089bcca7f", name: "kl;", description: "vcbghnjmk,l", is_active: true,…}
5: {id: "c0dcbaff-37d4-4e4c-9375-584ff7110d77", name: "dfhgbdcb", description: "dfxvcx", is_active: true,…},...
scannedCount: 100
I have followed these tutorials to get count HOW TO COUNT THE NUMBER OF RESULTS WITH AWS AMPLIFY DYNAMODB AND GRAPHQL
Filter
var body = {
filter: {
is_active: {
eq: true
}
}
}
Query to get list of todos
export const listTodos = /* GraphQL */ `
query ListTodos(
$filter: ModelTodoFilterInput
$limit: Int
$nextToken: String
) {
listTodos(filter: $filter, limit: $limit, nextToken: $nextToken) {
count
items {
id
name
description
is_active
createdAt
updatedAt
}
scannedCount
}
}
`;
GraphQl shema
type Todo #model {
id: ID!
name: String!
description: String!
is_active: Boolean
}
type ModelTodoConnection {
items: [Todo]
scannedCount: Int
count: Int
total: Int
}
And IF I set limit to 5 and it will send back scannedCount 5 if when I have total data in database around 110. I want to count data where is_active: { eq: true }

Check out the package I wrote to solve this issue: https://github.com/multimeric/AmplifyCountDirective.
After following the installation instructions, to solve your issue I would change the schema to this:
type Todo #model #count {
id: ID!
name: String!
description: String!
is_active: Boolean
}
Then you can query the count using a GraphQL query such as:
{
countTodo(filter: {
is_active: {
eq: true
}
})
}

Related

Can you apply sorting to a lists of models inside another model?

Using AWS Amplify, can we apply sorting to the messages in the Conversation model?
When fetching the conversation, it would be nice that the messages come sorted based on the generated createdAt date.
Currently these are the models used.
type Conversation #model {
id: ID!
messages: [Message!]! #hasMany
...
}
type Message #model {
id: ID!
authorId: String!
content: String!
conversation: Conversation #belongsTo
}
Ideally want to place sorting on the hasMany directive, but this is not possible.
type Conversation #model {
id: ID!
messages: [Message!]! #hasMany(sortKeys:['createdAt'])
...
}
Created a secondary index on the Message model with a sort field on createdAt.
type Message #model {
id: ID!
authorId: String! #index(name: "byAuthorId", queryField: "getMessagesByAuthorId", sortKeyFields: [ "createdAt" ])
content: String!
conversation: Conversation #belongsTo
}
Amplify created a new query to fetch the messages and apply sorting. Following example uses react-query to fetch the messages from an authorId with sorting.
export function useMessagesPerAuthorId({
id,
filter,
enabled = true,
}: {
id: string | undefined;
filter: any;
enabled?: boolean;
}) {
return useQuery(
['conversations', 'messages', id, filter],
() => fetchMessagesByAuthorId({ id: id!, filter }),
{ enabled: enabled && !!id }
);
}
async function fetchMessagesByAuthorId({ id, filter }: { id: string; filter: any }) {
const query: any = await API.graphql({
query: getMessagesByAuthorId,
variables: { authorId: id, sortDirection: 'DESC', filter },
});
const data: Message[] = query.data?.getMessagesByAuthorId.items;
return data;
}
Now we can call that hook in our view component and pass the filters.
const { isLoading, data: messages = [] } = useMessagesPerAuthorId({
id: profile?.id,
filter: {
and: [{ conversationMessagesId: { eq: conversationId } }, { deleted: { eq: false } }],
},
enabled: !!profile?.id,
});

Sorting AWS AppSync 'GraphQL' connected queries (nesting sorting?)

I am Using AWS AppSync for my react native application and can't seem to figure out how to get sort inside of a query (nested queries/sorting?). Not sure what the proper terminology would be but here are my graphQL models, each month can contain many monthsPhotos:
type Month
#model
#auth(rules: [{ allow: owner, operations: [read, create, delete, update] }]) {
id: ID!
name: String!
owner: String!
monthsphotos: [MonthPhoto] #hasMany
createdAt: AWSDateTime!
updatedAt: AWSDateTime!
sorttype: String!
#index(
name: "monthsByDateTime"
queryField: "monthsByDateTime"
sortKeyFields: ["createdAt"]
)
}
type MonthPhoto
#model
#auth(rules: [{ allow: owner, operations: [read, create, delete, update] }]) {
id: ID!
month: Month #belongsTo
thumbnail: String
owner: String!
caption: String
location: String
date: String
createdAt: AWSDateTime!
updatedAt: AWSDateTime!
monthMonthsphotosId: ID!
#index(
name: "monthPhotosByDateTime"
queryField: "monthPhotosByDateTime"
sortKeyFields: ["createdAt"]
)
file: S3Object
}
my query for my months looks like this:
export const monthsByDateTime = /* GraphQL */ `
query MonthsByDateTime(
$sorttype: String!
$createdAt: ModelStringKeyConditionInput
$sortDirection: ModelSortDirection
$filter: ModelMonthFilterInput
$limit: Int
$nextToken: String
) {
monthsByDateTime(
sorttype: $sorttype
createdAt: $createdAt
sortDirection: $sortDirection
filter: $filter
limit: $limit
nextToken: $nextToken
) {
items {
id
name
monthsphotos {
items {
file {
bucket
region
key
}
createdAt
caption
date
location
}
}
}
}
}
`;
This lets me sort my months data by the date and time is was created. Ultimately I want a query that sorts all the months, and also sorts all the monthsPhotos within those months in 1 query. How would I go about doing this? Below is another query I made to sort monthsPhotos alone, I have not figured out how to connect these two into one:
export const monthPhotosByDateTime = /* GraphQL */ `
query MonthPhotosByDateTime(
$monthMonthsphotosId: ID!
$createdAt: ModelStringKeyConditionInput
$sortDirection: ModelSortDirection
$filter: ModelMonthPhotoFilterInput
$limit: Int
$nextToken: String
) {
monthPhotosByDateTime(
monthMonthsphotosId: $monthMonthsphotosId
createdAt: $createdAt
sortDirection: $sortDirection
filter: $filter
limit: $limit
nextToken: $nextToken
) {
items {
id
file {
bucket
region
key
}
caption
location
date
createdAt
monthMonthsphotosId
}
nextToken
}
}
`;

graphQL Query: getting error "Expected value of type ..., found ..."

Suppose I have the following object types:
type Price {
currency: Currency!,
amount: Float!
}
type Attribute {
displayValue: String,
value: String,
id: String!
}
type AttributeSet {
id: String!,
name: String,
type: String,
items: [Attribute]
}
type Product {
id: String!,
name: String!,
inStock: Boolean,
gallery: [String],
description: String!,
category: String!,
attributes: [AttributeSet]
prices: [Price!]!,
brand: String!
}
type Category {
name: String,
products: [Product]!
}
type Currency {
label: String!,
symbol: String!
}
input CategoryInput {
title: String!
}
type Query {
categories: [Category],
category(input: CategoryInput): Category,
product(id: String!): Product,
currencies: [Currency]
}
And these are the Types for Category:
export enum Category {
all = 'all',
clothes = 'clothes',
tech = 'tech'
};
In graphQL Playground, I am trying to make a query to exhibit all the names and products/id of the elements with the category all. Here's my attempt:
{
category(input: "all") {
name
products {
id
}
}
}
But I'm getting the following error message:
"message": "Expected value of type \"CategoryInput\", found \"all\".",
I need help trying to understand what went wrong since all is a valid type. Thank you in advance.
Just found my mistake
CategoryInput is of type
input CategoryInput {
title: String!
}
So a proper query would be:
{
category(input: { title: "all" }) {
name
products {
id
}
}
}

Prisma 2 query to return records only that are associated with ALL of the provided tag IDs

I have tables Principles and Tags. And there is a many-to-many relation between them (joined implicitly).
Without using prisma.raw, how can I run the following query?
SELECT p.id, p.title, p.description, p.createdAt, p.modifiedAt
FROM principle p
WHERE EXISTS (SELECT NULL
FROM _PrincipleToTag pt
WHERE pt.B IN (${tagIds.join(',')})
AND pt.A = p.id
GROUP BY pt.A
HAVING COUNT(DISTINCT pt.B) = ${tagIds.length})
How can I update this Prisma 2 query such that the principles returned are only principles that are associated with ALL of the provided tagIds?
export const principles = ({ tagIds }) => {
const payload = {
where: {
//TODO filter based on tagIds
},
}
return db.principle.findMany(payload)
}
The docs mention contains and in and every, but I can't find examples of what I'm trying to do.
I'm using RedwoodJs, Prisma 2, Apollo, GraphQL.
Update in response to comment: here is the SDL:
input CreatePrincipleInput {
title: String!
description: String
}
input CreatePrincipleWithTagsInput {
title: String!
description: String
tagIdsJson: String
}
input CreateTagInput {
title: String!
description: String
}
# A date string, such as 2007-12-03, compliant with the `full-date` format
# outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for
# representation of dates and times using the Gregorian calendar.
scalar Date
# A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the
# `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO
# 8601 standard for representation of dates and times using the Gregorian calendar.
scalar DateTime
type Mutation {
createPrinciple(input: CreatePrincipleInput!): Principle
createPrincipleWithTags(input: CreatePrincipleWithTagsInput!): Principle
updatePrinciple(id: Int!, input: UpdatePrincipleInput!): Principle!
deletePrinciple(id: Int!): Principle!
createTag(input: CreateTagInput!): Tag!
updateTag(id: Int!, input: UpdateTagInput!): Tag!
deleteTag(id: Int!): Tag!
}
type Principle {
id: Int!
title: String!
description: String!
tags: [Tag]
createdAt: DateTime!
modifiedAt: DateTime!
}
type Query {
redwood: Redwood
principles(searchQuery: String, tagIds: [Int]): [Principle!]!
tags: [Tag!]!
tagsByLabel(searchTerm: String): [TagCount!]!
tag(id: Int!): Tag!
}
type Redwood {
version: String
}
type Tag {
id: Int!
title: String!
principles: [Principle]
description: String
createdAt: DateTime!
modifiedAt: DateTime!
}
type TagCount {
id: Int!
title: String!
count: Int!
principles: [Principle]
description: String
createdAt: DateTime!
modifiedAt: DateTime!
}
# A time string at UTC, such as 10:15:30Z, compliant with the `full-time` format
# outlined in section 5.6 of the RFC 3339profile of the ISO 8601 standard for
# representation of dates and times using the Gregorian calendar.
scalar Time
input UpdatePrincipleInput {
title: String
description: String
}
input UpdateTagInput {
title: String
description: String
}
It doesn't look like you are using prisma 2. Prisma 2 uses models (not types) and has arrays classified like Principles[] vs [Principles]. Maybe Redwood does the conversion(Never used it).
I created your model in Prisma 2 and used the following command to get a single principle that has the two tags associated with it. Keep in mind the IDs in there are from my test dataset. Hopefully, you can modify this to your code. If not, please create a sandbox/playground with minimal code for us to test.
export const principles = async ({ searchQuery, tagIds }) => {
const payload = {
where: {
OR: [
{ title: { contains: searchQuery } },
{ description: { contains: searchQuery } },
],
userId: userIdFromSession,
},
}
if (tagIds.length) {
const whereAnd = []
tagIds.forEach((tagId) => {
whereAnd.push({
tags: { some: { id: tagId } },
})
})
payload.where.AND = whereAnd
}
const result = await db.principle.findMany(payload)
return result
}
You could try something like this
export const principles = ({ searchQuery, tagIds }) => {
const payload = {
where: {
OR: [
{ title: { contains: searchQuery } },
{ description: { contains: searchQuery } },
],
// using the `in` operator like this
tagId: { in: tagIds },
userId: userIdFromSession,
},
}
console.log('db.principle.findMany(payload)', payload)
return db.principle.findMany(payload)
}
That should do the trick!
I had to resort to using AND for something similar - hope this helps!
const tagIds = [9,6];
where: {
// ...
AND: tagIds.map(tagId => ({
tags: {
some: {
id: {
equals: tagId,
},
},
},
})),
}

graphql mutation gives syntax error: Expected Name

I am trying to implement mutations with a variable. But I get the following error:
"Syntax Error GraphQL request (3:22) Expected Name, found $
2: mutation {
3: createProperty($property) {
^
4: id
"
My schema definitely doesn't say anything about a name, that's why I think this error is so strange.. I also don't think the documentations about graphql / apollo are very good.
Calling the mutation from client:
const property = {
title: 'First house',
cost: 849,
bedrooms: 3,
bathrooms: 2,
car_spaces: 1,
house_size: 60,
};
const createPropertyQuery =
graphql(gql`
mutation {
createProperty($property) {
id
}
}
`, {
options: {
variables: {
property,
},
},
});
const { data } = await apolloClient.query({
query: createPropertyQuery,
});
Schema:
type Property {
title: String!
cost: Float
user: User
bedrooms: Int!
bathrooms: Int!
car_spaces: Int!
house_size: Int!
}
input propertyInput {
title: String!
cost: Float
bedrooms: Int!
bathrooms: Int!
car_spaces: Int!
house_size: Int!
}
type RootMutation {
createProperty (
property: propertyInput
): Property
}
You should mention name of the parameter at first!
mutation CreatePropertyMutatuin($property: propertyInput){
createProperty(property: $property) {
id
}
}

Resources