TheLearner
TheLearner

Reputation: 2863

GraphQL filtering on array field

I have a document with the following contents:

{
  "data": {
    "posts": [
      {
        "id": "5d9f1af799785458ed55fcf3",
        "title": "Lorem ipsum dolor sit amet, consectetuer adipiscing eli",
        "likedBy": {
          "readers": [
            "abc",
            "xyz",
            "mnp"
          ]
        }
      },
      {
        "id": "5d9f2afa9cf1b45a20edaf93",
        "title": "Sed ut perspiciatis unde omnis iste natus error sit volupt",
        "likedBy": null
      },
      {
        "id": "5d9f2d1cd12ce45b11e90920",
        "title": "But I must explain to you how all this mistaken idea of deno",
        "likedBy": null
      }
    ]
  }
}

Here, I have a field likedBy which is an object with an array as its value.

Now, I can run the following query to retrieve all documents:

{
  posts{
    id
    title
    likedBy
  }
}

However, is there any way to filter out specific values of the array at the query level? For instance, Say I want my output to look like this:

{
  "data": {
    "posts": [
      {
        "id": "5d9f1af799785458ed55fcf3",
        "title": "Lorem ipsum dolor sit amet, consectetuer adipiscing eli",
        "likedBy": {
          "readers": [
            "abc",
          ]
        }
      },
      {
        "id": "5d9f2afa9cf1b45a20edaf93",
        "title": "Sed ut perspiciatis unde omnis iste natus error sit volupt",
        "likedBy": null
      },
      {
        "id": "5d9f2d1cd12ce45b11e90920",
        "title": "But I must explain to you how all this mistaken idea of deno",
        "likedBy": null
      }
    ]
  }
}

Here, I have returned all documents as before, except with only abc in the likedBy array. Is that possible with GraphQL?

Upvotes: 1

Views: 732

Answers (1)

Wai Ho Choy
Wai Ho Choy

Reputation: 346

Yes, you can. You can implement filtering at the graphql resolver function. This link to the Apollo Server graphql resolver should help even if you don't use Apollo Server to run your graphql server.

Here's what it could look like if you wanted to filter the reader by whether their name started with the letter "a", i.e. "abc". I am using SQL queries to illustrate data fetching (e.g. SELECT * FROM db_table) but you can replace it with any method to fetch data from a data source (database, excel file, document db, etc..)

// your query

query($startsWith: String) {
  posts{
    id
    title
    likedBy(startsWith: $startsWith) {
       readers
    }
  }
}

// the variables / input arguments you send with your query

{
   "startsWith": "a"
}

// The resolver function you might write that can filter by the reader's first alphabet (or any other condition)

const resolvers = {
   Query: {
      posts: function(root, args, context, info) {
         return context.db.query('SELECT * FROM posts')
      },
   },
   Posts: {
      id: function(parent, args, context, info){
         return parent.id // posts is the parent
      },
      title: function(parent, args, context, info){
         return parent.title
      },
      likedBy: function(parent, args, context, info){
         const postId = parent.id;

         const targetAlphabet = args.startsWith; // <= This is where your input ends up

         const allReadersWhoLikeThisPost = context.db.query(`SELECT DISTINCT * FROM readerLikes rl WHERE rl.liked_post_id = ${postId}`, 'collection')

         const readerNames = allReadersWhoLikeThisPost.map(reader => reader.name)

         // Filter for readers whose name starts with "a"
         const filteredReaderNames = readerNames.filter(name => name.substring(0,1) === targetAlphabet) 

         const reshapedData = {
             readers: filteredReaderNames
         }
         return reshapedData;
      }
   },

}

Upvotes: 3

Related Questions