Home > Mobile >  Javascript/Node array returns [object object] after spread operation
Javascript/Node array returns [object object] after spread operation

Time:12-13

I'm developing a Dating App which is similar to Tinder, right now, I'm working on node-express-mongodb-mongoose server and I'm stuck at a point. The problem is, when the app loads, in homepage, I want to fetch all the profiles excluding mine and the ones' which I have passed (disliked). Below is the route for this function in node:

User Schema:

const userSchema = new mongoose.Schema({
    email: {
        type: 'string',
        unique: [true, 'Email ID already present.'],
        required: true,
    },
    password: {
        type: 'string',
        required: true,
        minlength: 4,
    },
    displayName: {
        type: 'string',
        required: false,
        default: '',
    },
    photoURL: {
        type: 'string',
        required: false,
        default: '',
    },
    job: {
        type: 'string',
        required: false,
        default: '',
    },
    age: {
        type: 'number',
        required: false,
        default: null,
    },
    passes: {
        type: 'Array',
        required: false,
    },
    likes: {
        type: 'Array',
        required: false,
    },
    matches: {
        type: 'Array',
        required: false,
    }
  }
);

mongoose.model('User', userSchema);

Fetch Profiles Route:

const id = req.user._id;
    try {
        const currentUser = await User.findById({_id: id}); // gets the current user
        const passes = currentUser.passes; // gets the passed/disliked profiles (array of objects)
        const users = await User.find(); // gets all the registered users from db
        console.log(passes);
        const allUsers = [...passes, ...users]; // combining the 2 arrays 
        console.log('ALL USERS: '   allUsers);
        const usersAfterFilter = allUsers.filter(
            (user) => user._id.toString() !== id.toString() // finally filtering because I want to fetch all the profiles excluding mine and the ones' which I have passed.
        );
        console.log('ALL USERS AFTER FILTER: '   usersAfterFilter);
        res.send({'response': 'success', 'data': usersAfterFilter});
    } catch (error) {
        console.log(error.message);
        return res.status(422).send({response : error.message});
    }

The following is the log output:

[
  [
    {
      _id: new ObjectId("612131375a7fd116969e298c"),
      email: '',
      password: '',
      displayName: 'Yolo',
      photoURL: '',
      job: 'CEO of World',
      age: 22,
      passes: [],
      likes: [],
      matches: [],
      createdAt: 2021-12-12T10:38:47.967Z,
      updatedAt: 2021-12-12T10:39:14.943Z,
      __v: 0
    }
  ]
]
ALL USERS: [object Object],{
  _id: new ObjectId("612131375a7fd116969e298c"),
  email: '',
  password: '',
  displayName: 'Yolo',
  photoURL: '',
  job: 'CEO of World',
  age: 22,
  passes: [],
  likes: [],
  matches: [],
  createdAt: 2021-12-12T10:38:47.967Z,
  updatedAt: 2021-12-12T10:39:14.943Z,
  __v: 0
},{
  _id: new ObjectId("61b5d2395a7fd12347ae2994"),
  email: '',
  password: '',
  displayName: 'your actor',
  photoURL: '',
  job: 'Actor',
  age: 25,
  passes: [ [ [Object] ] ],
  likes: [],
  matches: [],
  createdAt: 2021-12-12T10:39:46.347Z,
  updatedAt: 2021-12-12T10:41:36.627Z,
  __v: 0
}
Cannot read properties of undefined (reading 'toString')

As you can see, when I combine the two array for filtering purpose, the ...passes converts to [object Object] and hence destroys the purpose of filtering because I cannot compare on the basis of id anymore.

I would really appreciate if someone could help me here!

CodePudding user response:

...when the app loads, in homepage, I want to fetch all the profiles excluding mine and the ones' which I have passed (disliked).

The following demonstrates how you could get the desired data. Assuming some documents in the collection users, the following run from the mongo shell.

Sample Documents:

{ _id: 1, passes: [ 3, 4, 5 ] }, { _id: 2 }, { _id: 3 }, { _id: 4 }, { _id: 5 }, { _id: 9 }

Note that the current user is with _id: 1 with passes: [ 3, 4, 5 ]. The output would be the ids: [ 2, 9 ].

The Queries:

You can use any one of the following approaches to get the desired result. The first way:

var currentUser = db.users.findOne({ _id: 1 });
var passedUsers = currentUser.passes;
var allUsers = db.users.find().toArray();
passedUsers.push(currentUser._id);
allUsers.filter(user => (passedUsers.findIndex(passedUser => user._id == passedUser)) == -1)

The output: [ { "_id" : 2 }, { "_id" : 9 } ]


The second approach:

var currentUser = db.users.findOne({ _id: 1 });
var passedUsers = currentUser.passes;
passedUsers.push(currentUser._id);
db.users.find( { _id: { $nin: passedUsers }} ).toArray();

The third way, and this uses a single aggregation query:

db.users.aggregate([
{ 
  $match: { _id: 1 } 
},
{ 
  $lookup: {
      from: "users",
      let: { idVar: "$_id" , passesVar: "$passes" },
      pipeline: [
          { 
            $match: { 
                $expr: { 
                    $not: { $in: [ "$_id", { $concatArrays: [ "$$passesVar" , [ "$$idVar" ] ] } ] }
                } 
            } 
          },
      ],
      as: "usersAfterFilter"
}},
{ 
  $project: { 
      usersAfterFilter: 1, 
      _id: 0 
}}
])

The output: { "usersAfterFilter" : [ { "_id" : 2 }, { "_id" : 9 } ] }

  • Related