Aggregate question

Hi.
I have 3 collections that I would like to get data from.

  1. users
  2. tags
  3. coordinates

I have managed to get all users within a $box of coordinates:

{
      $lookup: {
        from: 'users',
        localField: 'userId',
        foreignField: '_id',
        as: 'users'
      },
    },
{
      $match: {
        coordinates: { $geoWithin: { $box: [[lng2, lat2], [lng1, lat1]] } },
    },
}

This results with a group of users however I would like to ‘join’ the users tags which are in another collection:

tagName: {
    type: String,
    required: true,
  },
  userId: {
    type: Schema.Types.ObjectId,
    ref: 'User',
  },

I have added another $location:

{
      $lookup: {
        from: 'tags',
        localField: 'userId',
        foreignField: '_id',
        as: 'tags'
      },
    },

However, tags are empty.
Any ideas on how to get the tags to the representative userId?

Thank you

Hey @Michel_Larsson,

Can you add all 3 schemas to the question?

Hi and thanks for your respond.

Tags:

import mongoose from 'mongoose';

const Schema = mongoose.Schema;

const TagSchema = new mongoose.Schema({
  tagName: {
    type: String,
    required: true,
  },
  userId: {
    type: Schema.Types.ObjectId,
    ref: 'User',
  },
  createdDate: {
    type: Date,
    required: true,
    default: new Date()
  },
});

const Tag = mongoose.model('tags', TagSchema);

export default Tag;

User

const UserSchema = new mongoose.Schema({
  fullname: {
    type: String,
    required: true,
  },
  password: {
    type: String,
    required: true,
  },
  email: {
    type: String,
    required: true,
    unique: true
  },
  avatar: {
    type: String,
  },
  createdDate: {
    type: Date,
    default: new Date()
  },
  lastUpdated: {
    type: Date,
  },
  status: {
    type: String,
    enum: ['pending', 'active', 'deleted', 'banned'],
    default: 'pending'
  },
});
const User = mongoose.model('users', UserSchema);

Coordinates

const UserCoordinatesSchema = new Schema({
  userId: {
    type: Schema.Types.ObjectId,
    ref: 'User',
    required: true,
  },
  coordinates: {
    type: Object,
    required: true,
  },
  startDate: {
    type: Date,
  },
  endDate: {
    type: Date,
  },
  createdDate: {
    type: Date,
    default: new Date()
  },
});

const UserCoordinates = mongoose.model('usercoordinates', UserCoordinatesSchema);

Sorry Michel_Larsson, I flagged your post by mistake. I wanted to flagged the one from Ashley_Jaz.

Hopefully, a moderator will un-spam it to correct my mistake. In the meantime, while NeNaD is comfortable to work with mongoose schema, some like me, prefer sample documents. So it would be nice if you could share any.

Sorry, again for the mis-flagging.

I do not know mongoose but from

I suspect that in

you simply have to switch, localField and foreignField because in tags, userId is your ref:User.

1 Like

@Michel_Larsson As @steevej said, I think you just misconfigured the second $lookup. Based on your schemas, it should look like this:

{
  $lookup: {
    from: 'tags',
    localField: 'userId',
    foreignField: 'userId',
    as: 'tags'
  },
}

@steevej I think the aggregation query is run against coordinates collection, so both localField and foreignField should be the same - “userId”.


Side note - I suggest that you put $match stage before the $lookup stage. It should increase the performance of the query since $lookup will perform on fewer documents.

1 Like

More than a side note. A very important one:

1 Like