Iggy's Pop
Iggy's Pop

Reputation: 599

getting user data from ID's in array of objects

I haven't done much work with mongo so coming from mysql it is a bit of a challenge. What I want to do is get the data for the users in my friends array ie: their name, email etc. This is what I have below. When I hit a certain route I send my ID to the api endpoint. I then need to get the friend ID's from the array and get their relevant information.

Record in the database

{
    "_id": {
        "$oid": "5f1b22a427e4624711bdef0e"
    },
    "friends": [{
        "$oid": "5f206e15e9b66391246788d6"
    }, {
        "$oid": "5f2456777656525890dd9c21"
    }],
    "name": "Joe Smith",
    "email": "[email protected]",
    "mobile": "1233455467889",
}

Controller

exports.getAddedContacts = async (req, res) => {
  const userId = req.params.uid;
  let friends;

  try {
    friends = await User.find({ _id: userId });
  } catch (err) {
    res
      .status(500)
      .json({ error: "Something went wrong, could not get contacts" });
  }

  if (!friends || friends.length === 0) {
    res.status(404).json({ error: "No contacts found..." });
  }

  res.status(200).json({ friends: friends });
};

Upvotes: 0

Views: 775

Answers (1)

Milos Grujic
Milos Grujic

Reputation: 584

You could use an aggregation where you would use $match as the first stage in you pipeline just so you isolate only one user and then use populate to get your friends documents.

here is an example:

db.classes.insert( [
   { _id: 1, title: "Reading is ...", enrollmentlist: [ "giraffe2", "pandabear", "artie" ], days: ["M", "W", "F"] },
   { _id: 2, title: "But Writing ...", enrollmentlist: [ "giraffe1", "artie" ], days: ["T", "F"] }
])
db.members.insert( [
   { _id: 1, name: "artie", joined: new Date("2016-05-01"), status: "A" },
   { _id: 2, name: "giraffe", joined: new Date("2017-05-01"), status: "D" },
   { _id: 3, name: "giraffe1", joined: new Date("2017-10-01"), status: "A" },
   { _id: 4, name: "panda", joined: new Date("2018-10-11"), status: "A" },
   { _id: 5, name: "pandabear", joined: new Date("2018-12-01"), status: "A" },
   { _id: 6, name: "giraffe2", joined: new Date("2018-12-01"), status: "D" }
])
db.classes.aggregate([
   {
      $match: {
        _id: 1
      }
   }
   {
      $lookup:
         {
            from: "members",
            localField: "enrollmentlist",
            foreignField: "name",
            as: "enrollee_info"
        }
   }
])

You can find out more about this in official documentation

Just watch out for the result, aggregation always returns a list you so you have to do something like const [user] = await result.toArray()

Since you use mongoose you could also try using populate (check out docs) on your model like so:


const author = new Person({
  _id: new mongoose.Types.ObjectId(),
  name: 'Ian Fleming',
  age: 50
});

author.save(function (err) {
  if (err) return handleError(err);

  const story1 = new Story({
    title: 'Casino Royale',
    author: author._id    // assign the _id from the person
  });

  story1.save(function (err) {
    if (err) return handleError(err);
    // that's it!
  });
});

Story.
  findOne({ title: 'Casino Royale' }).
  populate('author').
  exec(function (err, story) {
    if (err) return handleError(err);
    console.log('The author is %s', story.author.name);
    // prints "The author is Ian Fleming"
  });

NOTE: I noticed in your question that you are storing what should be an array of ObjectID-s as an array of objects containing a single field string representing an ObjectID, this has to be changed if you want populate or lookup to work.

Upvotes: 1

Related Questions