Тип проблемы при использовании $в mikro orm mongodb

#node.js #mongodb #typescript #typegraphql #mikro-orm

#node.js #mongodb #typescript #typegraphql #mikro-orm

Вопрос:

Я использую mikro orm с mongodb для своего проекта. Пока это лучший orm для MongoDB в typescript. Но я сталкиваюсь с ошибками типа при использовании $in с идентификатором объекта. Вот мой код:

   @Query(() => [Post])
  async allPosts(@Ctx() { em }: appContext) {
    const posts = await em.find(Post, {});
    const repo = em.getRepository(Post)
    const multiplePosts = await repo.find({ _id: { $in: [new ObjectId("6005d0c253e2b72af07fc61a")] }  });
    console.log("multiplePosts: ", multiplePosts);
    return posts;
}
 

Post.ts

 export class Post {

  @Field(() => ID)
  @PrimaryKey()
  _id!: string;

  @Field(() => String)
  @Property()
  createdAt = new Date();

  @Field(() => String)
  @Property({ onUpdate: () => new Date() })
  updatedAt = new Date();

  @Field(() => String)
  @Property()
  title!: string;

  @Field(() => String)
  @Property()
  excerpt!: string;

  @Field(() => String)
  @Property()
  content!: string;

  @Field()
  @ManyToOne()
  author!: User;
}
 

Вот ошибка, которую я получаю:

 src/resolvers/PostResolver.ts:32:43 - error TS2769: No overload matches this call.
  Overload 1 of 2, '(where: FilterQuery<Post>, options?: FindOptions<Post, any> | undefined): Promise<Post[]>', gave the following error.      
    Argument of type '{ _id: { $in: ObjectId[]; }; }' is not assignable to parameter of type 'FilterQuery<Post>'.
      Types of property '_id' are incompatible.
        Type '{ $in: ObjectId[]; }' is not assignable to type 'string | RegExp | OperatorMap<FilterValue2<string>> | FilterValue2<string>[] |n 
ull | undefined'.
          Types of property '$in' are incompatible.
            Type 'ObjectId[]' is not assignable to type 'FilterValue2<string>[]'.
              Type 'ObjectId' is not assignable to type 'FilterValue2<string>'.
                Type 'ObjectId' is missing the following properties from type 'RegExp': exec, test, source, global, and 13 more.
  Overload 2 of 2, '(where: FilterQuery<Post>, populate?: any, orderBy?: QueryOrderMap | undefined, limit?: number | undefined, offset?: number | undefined): Promise<...>', gave the following error.
    Argument of type '{ _id: { $in: ObjectId[]; }; }' is not assignable to parameter of type 'FilterQuery<Post>'.
      Types of property '_id' are incompatible.
        Type '{ $in: ObjectId[]; }' is not assignable to type 'string | RegExp | OperatorMap<FilterValue2<string>> | FilterValue2<string>[] | null | undefined'.
          Types of property '$in' are incompatible.
            Type 'ObjectId[]' is not assignable to type 'FilterValue2<string>[]'.

32     const multiplePosts = await repo.find({
                                             ~
33       _id: { $in: [new ObjectId("6005d0c253e2b72af07fc61a")] },
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34     });
   ~~~~~


    at createTSError (D:blogservernode_modulests-nodesrcindex.ts:513:12)
    at reportTSError (D:blogservernode_modulests-nodesrcindex.ts:517:19)
    at getOutput (D:blogservernode_modulests-nodesrcindex.ts:752:36)
    at Object.compile (D:blogservernode_modulests-nodesrcindex.ts:968:32)
    at Module.m._compile (D:blogservernode_modulests-nodesrcindex.ts:1056:42)
    at Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
    at Object.require.extensions.<computed> [as .ts] (D:blogservernode_modulests-nodesrcindex.ts:1059:12)
    at Module.load (node:internal/modules/cjs/loader:973:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Module.require (node:internal/modules/cjs/loader:997:19)
 

Удаление ObjectId делает компилятор typescript счастливым, но тогда MongoDB не обрабатывает их как идентификатор объекта.

Отредактировано: кроме того, добавление //ts-ignore работает нормально, так что это проблема типа.

Ответ №1:

Проблема возникает из-за вашего определения сущности, где вы явно указываете, что _id тип is string , not ObjectId . Итак, если это идентификатор объекта, исправьте определение:

   @PrimaryKey()
  _id!: ObjectId;
 

Тогда ваш запрос должен пройти. Обратите внимание, что вы также можете определить сериализованный PK id: string , который будет действовать как виртуальный получатель для строковой версии ObjectId.

https://mikro-orm.io/docs/usage-with-mongo/

Возможно, вам потребуется установить @types/mongodb .

В общем случае, если тип свойства — ObjectId, запрос также можно выполнить в строковой форме. Они должны быть равны:

 repo.find({ _id: { $in: [new ObjectId("6005d0c253e2b72af07fc61a")] } });
repo.find({ _id: { $in: ["6005d0c253e2b72af07fc61a"] } });
repo.find({ _id: [new ObjectId("6005d0c253e2b72af07fc61a")] });
repo.find({ _id: ["6005d0c253e2b72af07fc61a"] });
repo.find([new ObjectId("6005d0c253e2b72af07fc61a")]);
repo.find(["6005d0c253e2b72af07fc61a"]);
 

Также обратите внимание, что, если вы не используете ts-morph, вы должны указывать явные типы там, где вы используете инициализатор свойства:

   @Property()
  createdAt: Date = new Date();
 

https://mikro-orm.io/docs/metadata-providers/#limitations-and-requirements

Комментарии:

1. Спасибо за ваш ответ. Это была ошибка, которую я делал. Я проверил эту ссылку и соответствующим образом отредактировал объект: @PrimaryKey() _id!: ObjectId; @Field(() => ID) @SerializedPrimaryKey() id!: string но теперь `const multiplePosts = await repo.find({ id: { $in: [new ObjectId(«6005d0c253e2b72af07fc61a»)] }, });` выдает мне ошибку.

2. Да, это должно быть совершенно очевидно. Зачем вам передавать objectid в свойство string?

3. Я нашел это в документах: mikro-orm.io/docs/usage-with-mongo /… На нем _id и id совпадают

4. Ну, они не совпадают, один вводится как string, другой как objectid. И это точно такая же проблема, как и ваша оригинальная. Это может быть возможно программно, мы говорим о проблемах с TS, а не об ошибках во время выполнения.

5. Вы всегда можете использовать expr помощник, чтобы обойти проблемы с типизацией : repo.find({ [expr('_id')]: ["6005d0c253e2b72af07fc61a"] }); .