graphql-compose/graphql-compose-elasticsearch

example with addFields

Closed this issue · 5 comments

I am trying to use addFields on my EsTC object, but the data comes up as empty object - could you provide an example of addFields in your documentation?

const ListingTypeComposer = composeWithElastic({
  elasticClient,
  elasticIndex,
  elasticMapping,
  elasticType,
  graphqlTypeName,
})

ListingTypeComposer.addFields({
  address: {
    type: GraphQLString,
    resolve: (source) => {
      console.log('here is the source', source)
      // above, source returns as {}
      // even though data is coming back in my ListingTypeComposer.resolve
      return source.addressLine1
    }
  },
})

If you could provide a working example in the readme of how addField can be used on top of graphql-compose-elasticsearch id really appreciate it

nodkz commented

Try to modify needed Type inside Resolver:

// ListingTypeComposer.getResolver('search').getTypeComposer().getFieldTC('hits').addFields({
// shortand
ListingTypeComposer.get('$search.hits').addFields({
  address: {
    type: 'String', //   <--- use short syntax, graphql-compose understood such things
    resolve: (source) => {
      console.log('here is the source', source)
      // above, source returns as {}
      // even though data is coming back in my ListingTypeComposer.resolve
      return source.addressLine1
    }
  },
})

In this example we get search resolver, then take its output type as TypeComposer object, then step down to hits field (which will have elasticsearch row data) and modify this field type by addin to it address field.

Thanks for the quick response. Ill try this out and update the issue if it works!

This is great @nodzk, this lets me do exactly what I want to. I'm wondering if you can help me with a more complex example

I want to resolve a field as 1 of 2 separate fields

import { ListingTypeComposer } from '../esListing'

const path = '$search.hits._source'

// https://graphql-compose.github.io/docs/en/api-TypeComposer.html

export const desktopPhone = {
  type: 'String',
  resolve: (
    source: any,
    args: { isSem?: boolean } = {},
  ) => {
    return args.isSem
      ? source.semtollfree
      : source.webtollfree
  },
  args: {
    isSem: { type: 'Boolean' },
  },
}

const customFields = {
  desktopPhone,
}

export default ListingTypeComposer
  .get(path)
  .addFields(customFields)
  .getResolver('search')
  .getFieldConfig()

In the above example, I can query for desktop phone with the given query

query {  
  listing(listingId: "2016242") {
    hits {
      _source {
        desktopPhone(isSem: true) 
        semtollfree < ----- id rather omit this and the next field
        webtollfree
      }
    }
  }
}

However, i'd like to be able to omit semtollfree and webtollfree from the query all together. Using graphql-compose, how can I fashion the request for desktopPhone to automatically resolve semtollfree and webtollfree in the source?

so I could end up doing something like this

query {  
  listing(listingId: "2016242") {
    hits {
      _source {
        desktopPhone(isSem: true) <--- allows resolution of semtollfree and webtollfree
      }
    }
  }
}

of course semtollfree and webtoll free exist in my es mapping where desktop phone does not

nodkz commented

Just remove this fields from your type:

ListingTypeComposer.get('$search.hits').removeField(['semtollfree', 'webtollfree'])

How I remember elastic returns completely all fields for hits.source. If it not happens (you will get empty data for your desktopPhone field. You may try to use projection property for requiring needed fields (request fields from db in programattic way if desktopPhone field present in query):

export const desktopPhone = {
  type: 'String',
  resolve: (source: any, args: { isSem?: boolean } = {}) => {
    return args.isSem
      ? source.semtollfree
      : source.webtollfree
  },
  args: {
    isSem: { type: 'Boolean' },
  },
  projection: {
    semtollfree: true,
    webtollfree: true,
  }
}

Hope this will work.

@nodkz thank you so much for your work and your responses. they have been very helpful