Search code examples
javascriptlodashgraphql

Graphql filter function returning all instead of specified ones


I wanna filter graphql query by giving arguments, but the problem is that even if in filter variables is specified the result is the all items. I'm using functions from lodash.

This is my filter function

export const resolvers = {
Query: {
    // allItems: (_, { value }) => getAllLinks().then(result => filter(result, {value: value})),
    allItems: (_, { value }) => getAllLinks()
        .then(result => filter(result, val => val.custom_attributes
            .filter(customVal =>
                customVal.attribute_code === 'category_ids' && isEqual(customVal.value , value) 
            ))),
    // allItems: (_, { value }) => getAllLinks().then(result => console.log(result)),
},

The most mindtwist thing for me is that, if I'll add

customVal.attribute_code === 'category_ids' && isEqual(customVal.value , value)
 ? console.log(customVal)
 : null

log will return me correct number of objects. That's my schema.

const typeDefs = `
    type Item  {
        id: ID!
        name: String
        price: Float
        custom_attributes: [CUSTOM_ATTRIBUTES]
    }

    union CUSTOM_ATTRIBUTES = CustomString | CustomArray 

   type CustomString {
    attribute_code: String
    value: String
  }

  type CustomArray {
    attribute_code: String
    value: [String]

  } 

  type Query {
    allItems(value : [String]): [Item]!

  }
`; 

Thanks for any advice.


Solution

  • The filter function iterates over each item in an array and returns a new array with the filtered items. If no items where found, it returns an empty array. An empty array evaluates as truthy.

    In your case, the outer filter filters the links (result). Each link that is evaluated by the outer filter function as truthy will be returned. The outer filter function uses the result of the inner filter, which is always an array, sometimes an empty one, but always a truthy value (provided no exception was thrown). In other words, the outer filter function will always return all links.

    Your console.log does log the items correctly because the code is executed even if we know it has no effect on the outer filter's result.

    A Possible Solution

    If you replace the inner call to val.custom_attributes.filter with val.custom_attributes.find then the inner find function will either return the custom_attribute which is an object and therefore truthy or it will return undefined if no item matches the criteria. Since undefined is falsy the outer filter function will not return items without the relevant custom attribute in the final result.