DEV Community

Cover image for Filter and Result (AWS Amplify, AppSync, GraphQL)
MD ARIFUL HASAN
MD ARIFUL HASAN

Posted on

Filter and Result (AWS Amplify, AppSync, GraphQL)

In this post, we'll try to understand how to search/filter and result work in AWS Amplify and AppSync.

Prerequisites:

1/ GraphQL Learn
2/ Data modeling
If you don't know about data modeling check out my previous blog about data-modeling

If you've no idea about any prerequisites, I recommend learning them highly.

Directives

@modal @auth @hasOne @hasMany @manyToMany @searchable @primaryKey @index

@searchable

  • Needs to setup ElasticSearch (We'll not do this in this post)
  • Active search and sorting at the same time.

other directives

  • I've briefly described other directives in the data-modeling blog. If you don't know about other directives click here to learn.

Data Types

  1. Scalar type: id, name, date_of_birth, got_job, gpa etc. (which has scalar value like ID, String, Float, Int, Boolean, AWSDate etc.)
  2. Object type: Status, Student ( which is a javascript object)

Image description

Supported Search Operations

Data Type Supported operations
String ne, eq, match, matchPhrase, matchPhrasePrefix, multiMatch, exists, wildcard, regexp
Int ne, gt, lt, gte, lte, eq, range
Float ne, gt, lt, gte, lte, eq, range
Boolean ne, eq
Enum ne, eq, match, matchPhrase, matchPhrasePrefix, multiMatch, exists, wildcard, regexp
Object not supported

ne (not equal), eq (equal), gt (greater than), lt (lesser than), gte (greater than or equal), lte (lesser than or equal)

Without @searchable directive

We can do filter with or without @searchable directive.We'll get filter argument for every list resolvers like (listStudents, listStatuses etc.)

  • Go to the DOCS or Documentation Explorer, and now search for the list resolver name you want to apply the filter. Click on any list resolver you want to apply filter. Here we're clicking on the liststudents resolver to apply the filter.
    Image description

  • Inside listStudents we get the filter argument. Click on the filter argument to see what conditions we can apply to filter out data.
    Image description

  • Inside filter argument, we can see multiple fields that can use to filter out data. If we pay attention to argument fields, we see that all the filter options are available only for the scalar field. No object fields are available like status
    Image description

Dummy data for testing:

We've created some data to test filtering. If you don't know how to add a document/data in database or how hasOne, hasMany, manyToMany relation works, I suggest you to check out the data-modeling blog. Now we'll apply filter on this below data

{
  "data": {
    "listStudents": {
      "items": [
        {
          "id": "9f928a7a-f096-4ad8-b0cc-5b354dde6b18",
          "name": "Raisa",
          "email": "raisa@gmail.com",
          "gpa": 3.7,
          "got_job": true,
          "statusID": "b3a4a939-50ed-4d3c-a21e-8048834391f5",
          "status": {
            "is_enrolled": true,
            "is_passed": false
          },
          "date_of_birth": "1998-07-17",
          "exam_completed": 2
        },
        {
          "id": "31092e63-e421-4bbc-afe8-f2092e309442",
          "name": "Ashim",
          "email": "ashim@gmail.com",
          "gpa": 3.2,
          "got_job": false,
          "statusID": "2cc614a4-0bd1-4a8d-80a8-bc0c8372788b",
          "status": {
            "is_enrolled": false,
            "is_passed": true
          },
          "date_of_birth": "1998-04-15",
          "exam_completed": 3
        },
        {
          "id": "9a3a92df-e4be-4258-ae02-502e0bfd3745",
          "name": "Hasan",
          "email": "hasan@gmail.com",
          "gpa": 3.4,
          "got_job": false,
          "statusID": "840a91da-75ce-4cd5-8a41-58081763a933",
          "status": {
            "is_enrolled": true,
            "is_passed": false
          },
          "date_of_birth": "1998-03-22",
          "exam_completed": 1
        },
        {
          "id": "ff173ed6-5749-4a54-903b-025675f828e5",
          "name": "Minhaj",
          "email": "minhaj@gmail.com",
          "gpa": 3.7,
          "got_job": true,
          "statusID": "e1f9ccc1-132f-443a-9f37-821ed634cfc1",
          "status": {
            "is_enrolled": true,
            "is_passed": false
          },
          "date_of_birth": "1998-04-21",
          "exam_completed": 3
        },
        {
          "id": "bc70feab-da91-4ba5-a626-ee99c9f4c4a0",
          "name": "Totul",
          "email": "totul@gmail.com",
          "gpa": 3.4,
          "got_job": false,
          "statusID": "ca9064ff-5c2f-4634-8dca-d12f10acd1db",
          "status": {
            "is_enrolled": false,
            "is_passed": true
          },
          "date_of_birth": "1998-03-29",
          "exam_completed": 1
        },
        {
          "id": "514b1115-7c95-4037-884f-4d5eae58dc4b",
          "name": "Mahadhi",
          "email": "mahadhi@gmail.com",
          "gpa": 3.6,
          "got_job": true,
          "statusID": "ec2d4c20-4022-4084-9d52-19ec2cd18503",
          "status": {
            "is_enrolled": false,
            "is_passed": true
          },
          "date_of_birth": "1993-07-21",
          "exam_completed": 4
        },
        {
          "id": "7054f363-3f3c-4343-9dff-f7e4491a797f",
          "name": "Shuvo",
          "email": "shuvo@gmail.com",
          "gpa": 2.5,
          "got_job": false,
          "statusID": "1958dea4-59b4-4766-b725-476747b8b4c3",
          "status": {
            "is_enrolled": false,
            "is_passed": true
          },
          "date_of_birth": "1998-02-15",
          "exam_completed": 2
        },
        {
          "id": "bf74457b-a1e4-4715-880f-1425bedaaa09",
          "name": "Ayesha",
          "email": "ayesha@gmail.com",
          "gpa": 3.5,
          "got_job": false,
          "statusID": "3a86016e-b0d6-479f-a1d1-1effa0846457",
          "status": {
            "is_enrolled": true,
            "is_passed": false
          },
          "date_of_birth": "1998-07-17",
          "exam_completed": 2
        },
        {
          "id": "a2e5e97d-5f8d-493e-ba78-1701ca08d58e",
          "name": "Arif",
          "email": "arif@gmail.com",
          "gpa": 3.51,
          "got_job": true,
          "statusID": "840a91da-75ce-4cd5-8a41-58081763a933",
          "status": {
            "is_enrolled": true,
            "is_passed": false
          },
          "date_of_birth": "1998-03-27",
          "exam_completed": 1
        },
        {
          "id": "485b3f5a-8709-4902-82a6-4997c6a0839a",
          "name": "Navin",
          "email": "navin@gmail.com",
          "gpa": 3.4,
          "got_job": false,
          "statusID": "0e437cee-92f6-418a-bf90-af74a67a9943",
          "status": {
            "is_enrolled": true,
            "is_passed": false
          },
          "date_of_birth": "1993-06-24",
          "exam_completed": 3
        }
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Using of filter argument: Filtering students by got_job

  1. got_job{ eq: $job }: Go to the documentation explorer and click on the **got_job field, we'll see some conditions with types like (eq: Boolean, ne: Boolean, etc.)

  2. $job: Boolean: Specify the input value type because we can only match with boolean data according to eq: Boolean
    Image description

Using of filter argument: Filtering students by gpa

  1. gpa{ ge: $point }: Go to the documentation explorer and click on the gpa field, we'll see some conditions with types like (ne: Float, ge: Float, eq: Float, etc.) We're using ge condition and its value is Float. That's why we've to take the float value

  2. $point: Float: Specify the input value type because we can only match with float number according to ge: Float
    Image description

Using of nested filter argument: Filtering students by gpa and got_job

Here we can use and / or / not operations. By default, and operation is applied on the query.

got_job : {eq: $job}, {exam_completed: {le: $exam}}: Data will show when got_job and exam_completed both satisfy conditions
Image description

Using of nested filter argument: Filtering students by got_job and exam_completed/email

got_job : {eq: $job}, or: [{exam_completed: {gt: $exam}}, {email: {eq: $email}}]: Data will show when got_job and exam_completed/email both satisfy conditions.
Image description

Using of limit & nextToken argument: Limiting data for pagination

$limit: Int:

  1. The limit argument takes an Integer value and gives a certain amount of data.
  2. Here we're providing the limit value 2. So the query will return a maximum of 2 documents/data.

$token: String:

  1. The nextToken argument takes a String value and gives the upcoming documents/data.
  2. Here we're providing an empty string in the argument because we need all data available in the first.
  3. We're also getting a nextToken string from the query field that will provide us with the upcoming data. If the nextToken value is null, that means we've no data left. Image description

$limit: Int:

  1. Here we're providing the limit value 2. So the query will return a maximum of 2 documents/data.

$token: String:

  1. Get the nextToken string from the previous query and provide it in the nextToken argument field to get upcoming documents/data.
  2. We're also getting a new nextToken string from the query field that will provide us with the upcoming data. Image description

Using of filter & limit & nextToken arguments:

We've already described all the conditions briefly, so now we will only visualize/understand the process.
Step-1| nextToken: "":
If the nextToken is an empty string, the limit process will start from 1st item/element.

Step-2| limit: 2:
The limit process will select 1st & 2nd item/element.

Step-3| filter: condition:
The filter process will check the 1st & 2nd item/element. If the filter condition satisfy, we will get the matched element. Here the condition matches with one element.
Image description

Step-1| nextToken: "":
If we provide a nextToken which we got from the previous query. The limit process will start from the upcoming item. Here the upcoming item starts from 3rd item/element.

Step-2| limit: 2:
The limit process will select 3rd & 4th item/element.

Step-3| filter: condition:
The filter process will check the 3rd & 4th item/element. If the filter condition satisfy, we will get the matched element. Here the condition matches with both elements.
Image description

Que: Here we are filtering data based on the student scalar field. What if we want to filter data based on student status (student object field)?

Solution:

  • Step-1: The connection between the Student model and the Status model is hasOne relation. We've to create a bi-directional relationship between the Student model and the Status model to get the Student data inside the Status model. If you don't understand relations between different models, check out this blog or feel free to comment below.
    Image description

  • Step-2: We've created a bi-directional relationship between both models. But if we don't update documents one by one, we'll get a null value. To get the student data inside the status table, we've to update every status providing status id in $id field and student id in $student_id field.
    Image description

  • Step-3: Get filtered data of enrolled students.
    Image description

With @searchable directive

By adding @searchable we get some extra operations

  • aggregation values, such as sum, average, min, max terms
  • retrieve total search result count
  • sort the search results across one or multiple fields

To work the @searchable directive properly, we've to setup OpenSearch, and that's for another blog

That's it for now. Thanks for your patience. If this blog help you please give a react.

Top comments (0)