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

How to populate items in array?

Open wizardnet972 opened this issue 5 years ago • 6 comments

I have in mongoose document collection with an array of documents:

export const DocumentsCollection = mongoose.model('Document-Collection',
  new mongoose.Schema({
    name: { type: String },
    items: [
      {
        name: { type: String },
        documents: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Document' }],
      },
    ],
  })
);

export const Document = mongoose.model( 'Document',
  new mongoose.Schema(
    {
      name: { type: String },
      description: { type: String }
    },
    { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } }
  )
);

I need to do a query that returns all the objects (findMany) with items populated.

The problem is items returns as an array of mongoids.

How to extend the findMany resolver to populate document object?

This is my expected query:

{
 documentCollectionMany {
   name,
  items {
    name
    _id,
    documents
  }
 }
}

Currently I getting this results:

{
  "data": {
    "documentCollectionMany": [
      {
        "name": "docgroup1",
        "items": [
          {
            "name": "cat1",
            "_id": "5ca37e1d21570b0011742473",
            "documents": [
              "5c6c0213f0fa853bd7d4a38c",
              "5c6c02948e0004a16529a1a1",
              "5c6c02ee7e76c62075850119",
              "5c6ef2ddd16e17889ffaffd0"
            ]
          }
        ]
      }
    ]
  }
}

@nodkz Is it something possible to do? because I can't find any working example.

wizardnet972 avatar Apr 10 '19 12:04 wizardnet972

https://graphql-compose.github.io/docs/basics/understanding-relations.html#relation-via-resolver

in your case it can look something like

DocumentCollectionTC.getFieldOTC('items').addRelation('documents', {
  resolver: () => DocumentTC.getResolver('findByIds'),
  prepareArgs: {
    _ids: source => source.documents || [],
  },
  projection: { documents: true },
});

nodkz avatar Aug 28 '19 08:08 nodkz

Thank you @nodkz ! I grateful for this package, and the solution to this topic. Maybe add this to the README ?! This helped me tremendously. It might help others.

SabrinaDanielle avatar Dec 16 '19 00:12 SabrinaDanielle

@SabrinaDanielle sure 👍

Can you add it to the end of FAQ section?

Tnx!

nodkz avatar Dec 18 '19 06:12 nodkz

https://graphql-compose.github.io/docs/basics/understanding-relations.html#relation-via-resolver

in your case it can look something like

DocumentCollectionTC.getFieldOTC('items').addRelation('documents', {
  resolver: () => DocumentTC.getResolver('findByIds'),
  prepareArgs: {
    _ids: source => source.documents || [],
  },
  projection: { documents: true },
});

@nodkz Is this still working for you? I'm finding that you can't populate a property that is of the same name as the array of ids. In this example the source of the ids is the documents property which is also the very same property you intend to populate. I'm using this exact example to attempt to populate items on an array and it only works if I have a documentIds array that I use as the _ids arguments source.

Does anyone know how to populate the same property?

danimayfield avatar Mar 26 '24 21:03 danimayfield

@danimayfield Did you try to use dataloader?

DocumentCollectionTC.getFieldOTC('items').addRelation('documents', {
  resolver: () => DocumentTC.mongooseResolvers.dataLoaderMany({ lean: true }),
  prepareArgs: {
    _ids: source => source.documents || [],
  },
  projection: { documents: true },
});

yurtaev avatar Mar 28 '24 04:03 yurtaev

@danimayfield Did you try to use dataloader?

Yes I did, it turns out it's a discriminator issue and projection isn't working: https://github.com/graphql-compose/graphql-compose-mongoose/issues/441 Which is why I ended up needing two separate properties, one to hold the ids and one to hold the full documents created by the addRelation for now

danimayfield avatar Mar 28 '24 15:03 danimayfield