graphql-compose / graphql-compose-mongoose

Mongoose model converter to GraphQL types with resolvers for graphql-compose https://github.com/nodkz/graphql-compose
MIT License
708 stars 94 forks source link

addRelation: projection not working as expected (with Federation) #370

Closed ddezoysa closed 3 years ago

ddezoysa commented 3 years ago

Hi,

I have the following relationship added to UserTC to fetch user's organizations. User schema has the _organizationIds field with list of organization ids.

export const UserSchema = new mongoose.Schema(
  {
    firstName: {
      type: String,
      required: true,
    },
    lastName: {
      type: String,
      required: true,
    },
    _organizationIds: [
      {
        type: Schema.Types.ObjectId,
        ref: 'Organization',
        index: true,
      },
    ],
  },
  { timestamps: true }
);

...

  UserTC.addRelation('organizations', {
    resolver: () => TCMap.OrganizationTC.getResolver('findByIds'),
    prepareArgs: {
      _ids: (source: IUser) => source._organizationIds,
      skip: null,
      sort: null,
    },
    projection: { _organizationIds: 1 },    <---
  });

Execution 01

When querying userFindMany with _organizationIds as a return fields,

QUERY:

query Query {
  userFindMany {
    id
    firstName
    lastName
    _organizationIds   <---
    organizations {
      name
    }
  }
}

RESPONSE:

{
  "data": {
    "userFindMany": [
      {
        "id": "611bdc46155bb03f6e39ef80",
        "firstName": "Dinuth",
        "lastName": "De Zoysa",
        "_organizationIds": [    <---
          "611e438239c2b7926d537358"
        ],
        "organizations": [    <---
          {
            "name": "MyOrg"
          }
        ]
      }
    ]
  }
}

MONGOOSE LOGS:

Mongoose: users.find({}, { limit: 100, projection: { id: true, firstName: true, lastName: true, _organizationIds: true, 'organizations.name': true }})
Mongoose: organizations.find({ _id: { '$in': [ ObjectId("611e438239c2b7926d537358") ] } }, { limit: 100, projection: { name: true } })

_organizationIds: true projection can be found in the query.

Execution 02

When querying userFindMany without _organizationIds as a return fields,

QUERY:

query Query {
  userFindMany {
    id
    firstName
    lastName
    organizations {
      name
    }
  }
}

RESPONSE:

{
  "data": {
    "userFindMany": [
      {
        "id": "611bdc46155bb03f6e39ef80",
        "firstName": "Dinuth",
        "lastName": "De Zoysa",
        "organizations": []     <---
      }
    ]
  }
}

MONGOOSE LOGS:

Mongoose: users.find({}, { limit: 100, projection: { id: true, firstName: true, lastName: true, 'organizations.name': true }})

_organizationIds: true projection can not be found in the query and organizations are not getting loaded.

But projection is set to for the required field _organizationIds in the relationship.

projection: { _organizationIds: 1 }, 

Expected behaviour is to fetch _organizationIds automatically obeying to the defined projection.

Please help to resolve this issue.

nodkz commented 3 years ago

It's quite strange. I wrote a test and everything is working as expected. Please see https://github.com/graphql-compose/graphql-compose-mongoose/commit/c2449a99cf1a4547619d414d405aa99b98630a18

ddezoysa commented 3 years ago

Hi @nodkz,

Thank you so much for the test. I tried your test and it works. When I compare my code with your test, the only difference is I'm creating a sub graph for federation.

Instead of this:

const schema = schemaComposer.buildSchema();

I have this:

const typeDefs = gql(schemaComposer.toSDL({ exclude: ['Boolean', 'String', 'Int'] }));
const resolvers = schemaComposer.getResolveMethods();

const federatedSchema = buildSubgraphSchema([{ typeDefs: mergeTypeDefs([typeDefs, customTypeDefs, gql(KeycloakTypeDefs)]) }]);
const schema = addResolversToSchema({
  schema: federatedSchema,
  resolvers: mergeResolvers([resolvers, customResolvers]),
  inheritResolversFromInterfaces: true,
});

When I revert it back to buildSchema as per your test it works.

Instead of using buildSubgraphSchema method, I tried with buildFederatedSchema method as well. But issue persists.

const schema = buildFederatedSchema([
  { typeDefs: gql(KeycloakTypeDefs) },
  { typeDefs, resolvers: resolvers as any },
  { typeDefs: customTypeDefs, resolvers: customResolvers },
]);

Any suggestions on why it is not working with Federation?

github-actions[bot] commented 3 years ago

:tada: This issue has been resolved in version 9.6.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

ddezoysa commented 3 years ago

Hi @nodkz, Issue still persists in version 9.6.0 as well with federation. Do you have a test case with federation for this?

nodkz commented 3 years ago

Maybe the federation recreates graphql types under the hood and removes projection field. Please try the following solution https://github.com/graphql-compose/graphql-compose-mongoose/issues/377#issuecomment-921143508

weibin159 commented 2 years ago

I tried the solution #377 (comment) but issue still persists. Is there any update?