0

I'm trying to build the following use case of DataLoader together with Mongoose:

export const PurchaseOrderType = new GraphQLObjectType({
    name: "PurchaseOrder",
    description: "PurchaseOrder",
    interfaces: () => [NodeInterface],
    isTypeOf: value => value instanceof PurchaseOrderModel,
    fields: () => ({
        id: {
            type: new GraphQLNonNull(GraphQLID),
            resolve: obj => dbIdToNodeId(obj._id, "PurchaseOrder")
        },
        name: {
            type: new GraphQLNonNull(GraphQLString)
        },
        customer: {
            type: CustomerType,
            resolve: (source, args, context) => {
                return context.customerLoader.load(source.customer_id);
            }
        }
    })
});

export default () => {
    return graphqlHTTP((req, res, graphQLParams) => {
        return {
            schema: schema,
            graphiql: true,
            pretty: true,
            context: {
                customerLoader: customerGetByIdsLoader()
            },
            formatError: error => ({
                message: error.message,
                locations: error.locations,
                stack: error.stack,
                path: error.path
            })
        };
    });
};



export const customerGetByIdsLoader = () =>
    new DataLoader(ids => {
        return customerGetByIds(ids);
    });


export const customerGetByIds = async ids => {
    let result = await Customer.find({ _id: { $in: ids }, deletedAt: null }).exec();

    let rows = ids.map(id => {
        let found = result.find(item => {
            return item.id.equals(id);
        });

        return found ? found : null; << === found always undefined
    });

    return rows;
};

I'm facing the following problems when loading several PurchaseOrders:

  1. A single customer_id is being called more than once in the ids parameter of the DataLoader. So an example id 5cee853eae92f6021f297f45 is being called on several requests to my loader, in successive calls. That suggests that the cache is not working properly.

  2. My found variable when processing the read result is always being set to false, even comparing the right ids.

halfer
  • 19,824
  • 17
  • 99
  • 186
Mendes
  • 17,489
  • 35
  • 150
  • 263

1 Answers1

0

You can use findOne

export const customerGetByIds = async ids => {
   let result = await Customer.find({ _id: { $in: ids }, deletedAt: null }).exec();
   const rows = []
   let promiseAll = ids.map(async (id) => {
      let found = result.filter(item => item.id.toString() === id.toSring());
      if(found) {
         rows.push(found[0])
         return found[0] 
      }
      return null; 
   });
   await Promise.all(promiseAll);
   return rows;
};
Ashok
  • 2,846
  • 1
  • 12
  • 20
  • This is not an acceptable answer as `findOne` will lead to multiple database calls, thus exponentially increasing the load time of data. – Mendes Sep 17 '19 at 12:48
  • Ok got you. Is the above solution not working at your end? – Ashok Sep 17 '19 at 13:04
  • Not even tested because as I said this will add not allowed delays. So, in short, this does not solve my problem. – Mendes Sep 17 '19 at 13:09