graphql-compose-mongoose icon indicating copy to clipboard operation
graphql-compose-mongoose copied to clipboard

`filter` Arguments cannot be used if `filter` in used in addRelation `prepareArgs`

Open hanzal opened this issue 5 years ago • 2 comments

I added a relation as below on Item

ItemTC.addRelation(
	'category',
	{
		resolver: () => CategoryTC.mongooseResolvers.findOne(),
		prepareArgs: {
			filter: (source) => ({
				_id: source.categoryId,
			}),
		},
		projection: { categoryId: 1 }, // point fields in source object, which should be fetched from DB
	}
);

When i try to make a query as below

query getHotelAndTableMappings($uniqueId: String) {
    itemOne {
      category(filter: (name:"test")){
        name
        _id
        icon_url
      }
      name
      tags
  }

It throws an error for filter argument.

filter can be used if I dont pass the prepareArg field while creating a relation. Is this the expected behaviour? Is the a way to fetch category related to item and also apply filters on it?

hanzal avatar Nov 29 '20 08:11 hanzal

@hanzal It's an expected behaviour as described in the docs:

filter: (source) => value - hide filter arg form schema and at runtime evaluate its value

A way to achieve what you are looking for is by creating the relation via FieldConfig instead of using addRelation method.

You can follow the example in the docs or use something like this to replicate the default findOne resolver filter args:

ItemTC.addFields({
  category: {
    type: CategoryTC,
    description: 'Category for this item.',
    args: {
      filter: CategoryTC.mongooseResolvers.findOne().getArg('filter'),
    },
    resolve: (source, args) => {
      const prepareArgs = { _id: source.categoryId };
      const criteria = args.filter
        ? Object.keys(args.filter).reduce(
            (accumulated, key) => ({
              ...accumulated,
              [key]: args.filter[key],
            }),
            prepareArgs,
          )
        : prepareArgs;
      return DB.Categories.findOne(criteria); // Replace it with your own Category model.
    },
    projection: { categoryId: true },
  },
});

Have not tested it so it may fail, but can give you an idea of how to add a relation and be able to pass arguments.

balonsom avatar Dec 05 '20 19:12 balonsom

Yep, @balonsom provided I right solution 👍

addRelation under the hood creates a regular fieldConfig. And it provides a little bit of code sugar which helps to modify args (remove them).

@hanzal for your case better to create fieldConfig manually like above. But if you have any suggestions how addRelation can be improved - please let me know.

For now, I don't know what kind of configuration options should be provided to addRelation which

  • should be clear that you want to remove just one field from filter arg type
  • keep other fields with allowing merging with already provided arg value

nodkz avatar Dec 07 '20 13:12 nodkz