Filter query by result of other federated service

Hello! Thanks for any pointers/recommendations up front - I am trying to add filters to my federated graphql api (which has been super fun to learn about so far).

There are two services behind a gateway - the Accounts service and the Users service.

Within the Users service, I extend the Account type to add a list of users to each account, that way I can query for accounts and get a list of users. I want to be able to query the accounts service for accounts that have > 0 users, but can not figure out how to do this.

// Users Type Defs
  type User @key(fields: "_id") @key(fields: "account") {
    _id: ID!
    first_name: String
    last_name: String
    phone: String
    address: Address
    email: String!
    created_by: User
    stripe_customer_id: String
    stripe_connected_account_id: String
    profile_img: ID
    createdAt: Date!
    updatedAt: Date!
    account: Account!
  }

  extend type Account @key(fields: "_id") {
    _id: ID! @external
    users(getUsersInput: GetUsersInput!): GetUsersResponse!
      @requires(fields: "_id")
  }

And accounts –

//Accounts Typedefs
  type Account @key(fields: "_id") {
    _id: ID!
    email: String!
    password: String
    role: Int!
    activation: Activation
    createdAt: Date!
    updatedAt: Date!
  }
// Users Resolver - resolving Account.users
// Basically this is just a Model.find() method from mongoose wrapped in a function that allows
// pagination and filtering

export const Account: AccountResolvers = {
  users: async (account, args) => {
    try {
      const { filters, options } = GenerateMongoFilter({
        fieldFilters: args.getUsersInput,
        config: {
          operator: "AND",
          pagination: args.getUsersInput.config?.pagination,
        },
        fieldRules: [
          {
            location: "account",
            fieldFilter: {
              string: account._id,
              filterBy: "OBJECTID",
            },
            disabled: false,
          },
        ],
      });

      const users = await FindWithPagination({
        options,
        filters: filters,
        model: Users,
      });

      return users;
    } catch (error) {
      console.log(error);
      throw error;
    }
  },
};

Right now I can query the accounts service and get a list of accounts but if they have no users, it returns an empty array for the users property. Any idea how I can query accounts with a variable to say “hey I only want the account returned if it has users?”

Thanks! Let me know if you need to see anything else!

Hello,

When extending an entity type you do not need to include the @requires to get the fields listed in the @key those are automatically passed on, so you can remove @requires(fields: "_id") from the users field.

You should implement this logic in the accounts service first, so wherever you have field to return the account you can return null instead. Then inside the resolver you would have to make a separate call to the Users DB after you got the accounts then return null. If it was an empty list.

The alternative is to not actually change anything and keep things the way they are so that it is a more clear schema contract. Why should you be limiting your clients to not get any account that doesn’t have any users? Unless they want the explicit specified in filters, the account data is still valid if it doesn’t have any users.

Thanks for the pointers. I did manage to come up with a solution for what I was trying to do!

I did not know about the automatic addition of the “_id” field! I’ll be doing some small refactoring to implement this. Thanks!

Hi!
Can you share the solution you came up with?
I’m struggling with a similar problem.
Thanks!

Hi @Nick_McLean , can you elaborate on your solution?