0

I have two related objects in my Mongoose data store connected by an ObjectId reference but when I have queried both sides of the relationship independently it seems surprisingly hard to match them up. The problem might be exaggerated because I am working in Typescript. For a stripped-down example, when I have a PlanUser who has many Plan objects:

export interface PlanUser {
    _id: string;

    name: string;

    email: string;
}

export interface Plan extends PlanSummary {

    _id: string;

    name: string;

    owner: PlanUser;

} 

class PlanUserSchemaClass {
    public static userSchema: Schema<PlanUser> = new Schema<PlanUser>({
        name: { type: String, required: true },
        email: { type: String, required: true },
    }, { autoCreate: false });

  public static planSchema: Schema<Plan> = new Schema<Plan>({
        name: { type: String, required: true },
        owner: { type: Schema.Types.ObjectId, ref: 'PlanUser' },
    }, { autoCreate: false });
}

export class PlanUserModel {

   private planModel = model('Plan', PlanUserSchemaClass.planSchema);

   private userModel = model('PlanUser', PlanUserSchemaClass.userSchema);

   public async findPlan( id: string, (next: Plan) => void) {
          await this.connect();
          const found = await this.planModel.findById(id);
          next(found);
   }

   public async findUser( id: string, (next: PlanUser) => void) {
          await this.connect();
          const user = await this.userModel.findById(id);
          next(user)
   }

}

Now I can query these well enough, the problem is that when I have queried them at separate points, I end up with this situation:

planUserModel.findUser('abc123', (user: PlanUser) => {
    planUserModel.findPlan('def456', (plan: Plan ) => {
        plan.owner == user // doesn't compile because Typescript thinks the owner is a PlanUser type
        plan.owner._id == user._id // false 
        plan.owner._id.toString() == user._id.toString() // true
    });
 });

The only test that seems to work consistently is casting both _id fields to strings.

As far as I can tell this is something to do with the ObjectId type; possibly because I am treating the _id fields as strings in my interface definition, but then Mongoose is populating them as ObjectIds at runtime. It makes sense for them to strings when I am passing them up to the UI which doesn't know what the back-end data store is. It's not a huge hassle to recast everything to perform the checks if that's necessary, but it feels inelegant and as though I am going against the flow of what Mongoose expects. What is the more correct way to do this?

glenatron
  • 11,018
  • 13
  • 64
  • 112

1 Answers1

2

The reference _id of an object is like that: new ObjectId('someidsomeid')

If you call toString() function, it's gonna be like that : 'someidsomeid'

So,

you can use string compare like that;

plan.owner._id.toString() == user._id.toString()

but, my suggestion use, equals()

plan.owner._id.equals(user._id)

here : Comparing mongoose _id and strings

Güray
  • 196
  • 6