Nested query returns empty array


#1

I want to get through a nested array with the id 456d456d67exa as our exemple here and get Car Name, after that go through the senders list and find the user with the id and get emails.address & profil.name
at the moment i get an empty array

Car.json :

{
    "_id": "456d456d67exa",
    "Name": "Apollo",
    "senders": [
        "zAxNarwAE2AnvPb8P",
        "Kz65arwAE2AnvPb8P",
        "Walaik56YDvWMShKY",
        "f2HA9Xc9hJNRuL5cp"
    ],
    "version": "4.2.0",
    "hardware": "5",
}

Exemple of a the document of the "_id": "zAxNarwAE2AnvPb8P", that i want to get the emails.adress + profile.name

{
    "_id": "zAxNarwAE2AnvPb8P",
    "createdAt": {
        "$date": "2018-04-16T09:45:10.212Z"
    },
 
"emails": [
    {
        "address": "Jean@paul.com",
        "verified": false
    }
],
"profile": {
    "features": {
        "pictures": false
    },
    "name": "Jean-Paul"
},
}

I want to get in a table the CarName + the senders ( email + name )

This is my car.type document

import {
  GraphQLString,
  GraphQLObjectType,
  GraphQLInt,
  GraphQLList,
} from 'graphql'
import { GraphQLSchema } from 'graphql';
import userType from '../user/user.type';

const carType = new GraphQLObjectType({
  name: 'Car',
  fields: () => ({
    _id: {
      type: GraphQLString,
      description: 'ID of the car'
    },
    idSender:{
      type: new GraphQLList(GraphQLString),
      description:'List of all senders'
    },
    UserList: {
       type: new GraphQLList(userType) 
    },
    name: {
      type: GraphQLString,
      description: 'Name of the car'
    },

  }),
    })
export default carType

This is my user.type

import {
  GraphQLString,
  GraphQLObjectType,
  GraphQLInt,
} from 'graphql'

const userType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    firstname: {
      type: GraphQLString,
      description: 'User\'s first name'
    },
    email: {
      type: GraphQLString,
      description: 'User\'s email address'
    },
  }),
})

export default userType

And this is what i’m trying to do but i get an empty array i’m pretty sure i’m doing something wrong

 GetInfo: {
    type: new GraphQLList(Car),
    resolve: async (_, args, { userId }) => {
      if (!userId) {
        throw new Meteor.Error(401, 'Unauthorized');
      }
      const userIterable = []
      await Cars.find({ senders: userId })
      .forEach((car) => {
         Meteor.users.find({
          UserList:'emails.address',? //( i want to get the emails.address + profile.firstname)
          // email:'emails.address'
        }).forEach((usr)=>{
          userIterable.push(usr)
        })

      })
      return userIterable
    }
  }

GraphQl Query Document Join
#2

Some of the logic I do not understand, but I don’t see you using car in the Meteor.users query.

      const userIterable = []
      await Cars.find({ senders: userId })
      .forEach((car) => {
         console.log("car: ", car);
         Meteor.users.find({ _id: { $in: car.senders } }, { fields: { emails: 1, profile: 1 } }).forEach((usr)=>{
          userIterable.push(usr)
        })

Maybe do some debugging with console.log() to see what data is pulling.


#3

I figure out how to got it, my problem now the senders field is empty but when i do a console.log i get all the data so i think it’s an async / await problem

there is my cod

await cars.forEach(async (car) => {
        await car.senders.slice(1).forEach(async (senderId) => {
          currentSender = await Meteor.users.findOne({ _id: senderId })
            currentSenders.push({
            email: currentSender.emails[0].address,
            firstname: currentSender.profile.name
          })
        console.log(car)
        })
        car.senders = currentSenders
        // car.senders =  await currentSenders
        // console.log(car)
        // currentSenders = []
      })

      return cars
    }
  }

when i do console.log(car.currentSenders) i get [] empty array, and when i do console.log(currentSenders) i get the name + email.

Things not working when i try to add the array in the object car


#4

Your issues are here in these lines:

await cars.forEach(async (car) => {
        await car.senders.slice(1).forEach(async (senderId) => {

You are awaiting an array in each case. Those array elements are Promises, not the resolved values. What you need to do is:

await Promise.all(cars.forEach(async (car) => {
  await Promise.all(car.senders.slice(1).forEach(async (senderId) => {
    currentSender = Meteor.users.findOne({ _id: senderId })
    currentSenders.push({
      email: currentSender.emails[0].address,
      firstname: currentSender.profile.name
    })
    console.log(car)
  }))
  car.senders = currentSenders
  // car.senders =  await currentSenders
  // console.log(car)
  // currentSenders = []
}))

return cars

Also, you do not need the await before the findOne (not an error - just not necessary).


#5

Thank you for your response sir, i get “message”: “Cannot read property ‘Symbol(Symbol.iterator)’ of undefined”,


#6

Have you done import { Promise } from 'meteor/promise'; in this file?


#7

Yes sir , i imported { Promise }


#8

Maybe i need to change the forEach and use a for loop ?


#9

Ah - my bad - for some reason I saw map, not forEach :roll_eyes: - sorry about that!

Okay, so forEach does not return an array.

In fact, you don’t need any awaits in there at all:

cars.forEach((car) => {
  car.senders.slice(1).forEach((senderId) => {
    currentSender = Meteor.users.findOne({ _id: senderId })
    currentSenders.push({
      email: currentSender.emails[0].address,
      firstname: currentSender.profile.name
    })
    console.log(car)
  })
  car.senders = currentSenders
  // car.senders =  await currentSenders
  // console.log(car)
  // currentSenders = []
})

return cars

#10

Welcome back Sir,

ForEach is not working so i figure out the problem by using a FOR LOOP my problem now is the array is populated imagine if in car.json i have 3 senders , and car2.json i have 7 senders.

when running my code

instead of having 3emails + 3 firstname for the first one & 7emails + 7 firstname for the second one

I always get 7.

So the loop is not doing correctly her job

 for (let car of cars){
    for (let senderId of car.senders.slice(1)) {


#11

forEach is an array prototype, for ... of is an iterable loop construct.

If cars is an array, they will exhibit similar behaviour:

['a', 'b', 'c'].forEach(x => console.log(x));
// a
// b
// c
for (x of ['a', 'b', 'c']) console.log(x);
// a
// b
// c

Are you expecting cars to be returned with each car object having its senders replaced by currentSenders? That will not work as you have written it. You are mutating variables in a function scope, which will not be available outside that scope.