Skip to content

How do you filter on a relationship field? #96

@danielmahon

Description

@danielmahon

OK. Ive been trying for hours now to get the right combination of addRelation, addFields and addFilterArg functions and I cannot seem to figure out how to allow for recursive(deep) filtering that will carry through to a populated field. I've had a hard time making sense of the previous github issues and notes/code that refer to similar methods.

Id basically like to pass a query like the following and retrieve only those images whose services contain the specified slug. I can make it work fine if I pass the service's _id but Id like to acheive the same results by matching the slug or any other attribute.

client query

query getImagesByServiceSlug {
  images(filter: { services: { slug : "my-service-slug" }}) {
    _id
    name
    services {
      _id
      slug
      name
    }
  }
}

Working findMany and findOne relationships (this also works with findByIds/findById)
This is a snippet of how I am mapping my mongoose models (via KeystoneJS) using graphl-compose-mongoose. This gets run for each model (list).

...

    const { model } = list;
    const name = keystone.utils.camelcase(model.modelName, true);

    const customizationOptions = {
      fields: {
        // Remove potentially sensitive data from GraphQL Schema
        remove: ['password'],
      },
    };

    types[key] = composeWithMongoose(list.model, customizationOptions);

    // Queries
    const queries = {};
    // model: find one
    queries[name] = types[key].getResolver('findOne');
    // models: find many
    queries[utils.plural(name)] = types[key].getResolver('findMany');
    schemaComposer.rootQuery().addFields({ ...adminAccess(queries) });

    // Mutations
    const mutations = {};
    // createModel: create new
    mutations[`create${utils.upcase(name)}`] = types[key].getResolver('createOne');
    // updateModel(record): update one
    mutations[`update${utils.upcase(name)}`] = types[key].getResolver('updateById');
    // deleteModel(): delete one
    mutations[`delete${utils.upcase(name)}`] = types[key].getResolver('removeOne');
    schemaComposer.rootMutation().addFields({ ...adminAccess(mutations) });

...

  // Define relationships
  _.each(lists, (list, key) => {
    _.each(list.relationshipFields, (field) => {
      const resolverName = pluralize.isPlural(field.path) ? 'findMany' : 'findOne';
      const resolver = types[field.options.ref].getResolver(resolverName);
      types[key].addRelation(field.path, {
        resolver,
        prepareArgs: {
          filter: source => ({
            [pluralize.isPlural(field.path) ? '_ids' : '_id']: source[field.path],
          }),
        },
        projection: { [field.path]: true },
      });
    });
  });

...

I've removed all my "attempts" to make it work because it was a mess so if you can help me from this point that would be great! Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions