0

As the title describe, it is always returns an empty array even when data is correct:

database.service.ts

async updateReply(id: string, attributes: Partial<ReplyDto>) {
    console.log('Path request update reply with id: ' + id + ' and body:', attributes);
    const reply = await this.replyModel.find({ _id: id });

    // This was the previous way of fetching and update the object:
    //
    // const reply = await this.replyModel.findOneAndUpdate(
    //     { _id: new mongoose.Types.ObjectId(id) },
    //     { $set: attributes },
    //     { new: true }
    // );
    
    console.log('Reply updated: ', reply);
    return reply;
}

replies.service.ts

async updateReply(id: string, body: UpdateReplyDto) {
    console.log('Path request update reply with id: ' + id + ' and body:', body);
    return await this.databaseService.updateReply(id, body);
}

replies.controller.ts

@Patch('/update/:id')
updateReplyById(@Param('id') id: string, @Body() body: UpdateReplyDto) {
    console.log('Path request update reply with id: ' + id + ' and body:', body);
    return this.repliesService.updateReply(id, body);
}

update-reply.dto.ts

import { IsArray, IsNumber, IsOptional, IsString } from "class-validator";

export class UpdateReplyDto {
    @IsString()
    @IsOptional()
    languageCode: string;

    @IsArray()
    @IsNumber({ allowNaN: false}, { each: true })
    @IsOptional()
    stars: string[];

    @IsArray()
    @IsOptional()
    keywords: string[];

    @IsArray()
    @IsOptional()
    comments: string[];
}

reply.dto.ts

import { Expose, Transform, Type } from "class-transformer";
import mongoose, { Types } from "mongoose";

export class ReplyDto {
    @Expose({ name: '_id' })
    // makes sure that when deserializing from a Mongoose Object, ObjectId is serialized into a string
    @Transform((value: any) => {
      if ('value' in value) {
        return value.value instanceof mongoose.Types.ObjectId ? value.value.toHexString() : value.value.toString();
      }
  
      return 'unknown value';
    })
    public id: string;

    @Expose()
    languageCode: string;

    @Expose()
    stars: string[];

    @Expose()
    keywords: string[];

    @Expose()
    comments: string[];

    @Expose()
    createdAt: Date;

    @Expose()
    updatedAt: Date;
}

Logs:

From Controller: Path request update reply with id: 62f6df243eb6410001621b90 and body: { languageCode: 'en', keywords: [ 'hey', 'you', 'friend', 'hello' ] }

From Service: Path request update reply with id: 62f6df243eb6410001621b90 and body: { languageCode: 'en', keywords: [ 'hey', 'you', 'friend', 'hello' ] }

From Database Service: Path request update reply with id: 62f6df243eb6410001621b90 and body: { languageCode: 'en', keywords: [ 'hey', 'you', 'friend', 'hello' ] }

.find Response: Reply updated: []

ytpm
  • 4,962
  • 6
  • 56
  • 113

2 Answers2

0

The answer lies in the commented part of the code:

const reply = await this.replyModel.find({ _id: id });

// This was the previous way of fetching and update the object:
//
// const reply = await this.replyModel.findOneAndUpdate(
//     { _id: new mongoose.Types.ObjectId(id) },
//     { $set: attributes },
//     { new: true }
// );

You need to convert id to ObjectId, try this:

const reply = await this.replyModel.find({ _id: new mongoose.Types.ObjectId(id) });
Charchit Kapoor
  • 8,934
  • 2
  • 8
  • 24
  • Already did that, that's why the code is commented out :) it returns an empty array... – ytpm Aug 23 '22 at 14:54
  • Ohh, that is also returning empty array – Charchit Kapoor Aug 23 '22 at 15:05
  • I suggest you, to enable query logging in Mongoose, following this post https://stackoverflow.com/questions/18762264/log-all-queries-that-mongoose-fire-in-the-application. Then you can see if the id is being passed as expected or not – Charchit Kapoor Aug 23 '22 at 15:52
0

I found the answer, the problem was occured because I want to change the _id key to id by doing this:

@Expose({ name: '_id' })
// makes sure that when deserializing from a Mongoose Object, ObjectId is serialized into a string
@Transform((value: any) => {
  if ('value' in value) {
    return value.value instanceof mongoose.Types.ObjectId ? value.value.toHexString() : value.value.toString();
  }

  return 'unknown value';
})
public id: string;

But actually the correct way was just to @Expose() the id: string;.

ytpm
  • 4,962
  • 6
  • 56
  • 113