Выберите атрибуты в репозитории.find() с отношениями (TypeORM)

Мой метод возвращает объект счета со всем объектом пользователя. Я хотел бы, чтобы я возвращал только объект счета и пользователя с двумя атрибутами в сущности. Я использую TypeORM

  /**
   * Returns a bills by account bill
   */
  async getByAccountBill(
    accountBill: string,
    id?: number
  ): Promise<Object | undefined> {
    const userService = new UserService();
    const user = await userService.getById(id);

    const bills = await this.billRepository.find({
      select: ["accountBill"],
      where: {
        accountBill: Like(`${accountBill}%`),
        user: Not(`${user.id}`)
      },
      relations: ["user"] // I get All object Entity (userId, password, login...) I want to only name and surname
    });

    if (bills) {
      return bills;
    } else {
      return undefined;
    }
  }
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
21
0
52 746
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Для этого вы можете использовать конструктор запросов, который является одним из самых мощных инструментов TypeOrm.

const values = this.billRepository.createQueryBuilder("bill")
    .leftJoinAndSelect("bill.user", "user")
    .where("bill.accountBill LIKE :accountBill", {accountBill})
    .andWhere("user.id = :userId", {userId: user.id})
    .select(["user.name", "user.surname"])
    .execute();
// NOTE
// .execute() will return raw results.
// To return objects, use .getMany()

Метод «выполнить» возвращает необработанный результат, поэтому, возможно, вам лучше использовать getMany, который возвращает объект

splhead 15.10.2020 23:08

Привет @zenbeni, я пытаюсь сделать что-то подобное, но он вернет undefined, если нет пользователя и andWhere условие не выполняется. Как заставить работать тот же запрос, если в таблице отношений еще нет записей?

Abrar 17.06.2021 00:10

В вопросе явно упоминается метод find(). Мы хотим полагаться на проводку, которую мы уже сделали в модели. Построитель запросов — мощный инструмент, но его следует использовать только в сложных запросах, где, на мой взгляд, недостаточно связывания модели. Вопрос включает простой запрос.

hadaytullah 18.01.2022 12:14

@hadaytullah, вы не можете использовать проводку базовой модели, так как получение только 2 полей в User полностью выходит за рамки ванильной модели, которая включает гораздо больше полей. Для этого вы должны использовать пользовательский запрос для сопоставления объектов. Таким образом, построитель запросов, это для меня правильный инструмент.

zenbeni 18.01.2022 18:05

Поскольку typeOrm не применяет выбор к объединенной таблице, мы можем использовать машинописный код Array.map() для удаления ненужных атрибутов из коллекции. Это не мудрое решение, если коллекция слишком велика. Но в то же время такое сопоставление все равно происходит на сервере базы данных, если мы используем построитель запросов с включенным в запрос выбором. Итак, мы просто перенесли эту обработку с сервера БД на сервер API. Время отклика будет хорошей метрикой, чтобы решить, какое решение find+Array.map VS querybuilder подходит для вашего приложения.

hadaytullah 19.01.2022 20:02

Данные - это то, где производительность, вы подразумеваете большее использование сети с вашим предлагаемым решением, больше операций ввода-вывода в базе данных, поскольку вы получаете больше данных, чем вам нужно (в большинстве случаев ввод-вывод и сеть более важны, чем любые оптимизации алгоритма в памяти ). Также вы добавляете нестандартное использование структур данных и TypeOrm с пользовательским кодом, который вам придется поддерживать впоследствии (в отличие от классического использования API-интерфейса querybuilder). Удаление данных столбца после их явного извлечения из базы данных в лучшем случае неоптимально, и его следует избегать с точки зрения производительности.

zenbeni 19.01.2022 23:16

Именно ограничения моделирования typeORM привели к использованию построителя запросов или ванильного кода. Я предполагаю, что когда модели разрешат более сложные соединения, в них отпадет необходимость. Sequalize — это немного более зрелая ORM, в которой можно выполнять множество сложных объединений.

hadaytullah 03.02.2022 12:33

Если кого-то заинтересует, краткий список кода, связанного с отношением, и ссылки на репо...

https://github.com/typeorm/typeorm/blob/master/src/find-options/FindOptionsUtils.ts

    /**
     * Applies give find options to the given query builder.
     */
    static applyOptionsToQueryBuilder<T>(qb: SelectQueryBuilder<T>, options: FindOneOptions<T> | FindManyOptions<T> | undefined): SelectQueryBuilder<T>;
...
        if (options.loadRelationIds === true) {
            qb.loadAllRelationIds();
        }
        else if (options.loadRelationIds instanceof Object) {
            qb.loadAllRelationIds(options.loadRelationIds);
        }

https://github.com/typeorm/typeorm/blob/master/src/query-builder/SelectQueryBuilder.ts

/**
 * Loads all relation ids for all relations of the selected entity.
 * All relation ids will be mapped to relation property themself.
 * If array of strings is given then loads only relation ids of the given properties.
 */
loadAllRelationIds(options?: { relations?: string[], disableMixedMap?: boolean }): this { // todo: add skip relations
    this.expressionMap.mainAlias!.metadata.relations.forEach(relation => {
        if (options !== undefined && options.relations !== undefined && options.relations.indexOf(relation.propertyPath) === -1)
            return;

        this.loadRelationIdAndMap(
            this.expressionMap.mainAlias!.name + "." + relation.propertyPath,
            this.expressionMap.mainAlias!.name + "." + relation.propertyPath,
            options
        );
    });
    return this;
}

/**
 * LEFT JOINs relation id and maps it into some entity's property.
 * Optionally, you can add condition and parameters used in condition.
 */
loadRelationIdAndMap(mapToProperty: string, relationName: string, options?: { disableMixedMap?: boolean }): this;

/**
 * LEFT JOINs relation id and maps it into some entity's property.
 * Optionally, you can add condition and parameters used in condition.
 */
loadRelationIdAndMap(mapToProperty: string, relationName: string, alias: string, queryBuilderFactory: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>): this;

/**
 * LEFT JOINs relation id and maps it into some entity's property.
 * Optionally, you can add condition and parameters used in condition.
 */
loadRelationIdAndMap(mapToProperty: string,
                     relationName: string,
                     aliasNameOrOptions?: string|{ disableMixedMap?: boolean },
                     queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>): this {

    const relationIdAttribute = new RelationIdAttribute(this.expressionMap);
    relationIdAttribute.mapToProperty = mapToProperty;
    relationIdAttribute.relationName = relationName;
    if (typeof aliasNameOrOptions === "string")
        relationIdAttribute.alias = aliasNameOrOptions;
    if (aliasNameOrOptions instanceof Object && (aliasNameOrOptions as any).disableMixedMap)
        relationIdAttribute.disableMixedMap = true;

    relationIdAttribute.queryBuilderFactory = queryBuilderFactory;
    this.expressionMap.relationIdAttributes.push(relationIdAttribute);

    if (relationIdAttribute.relation.junctionEntityMetadata) {
        this.expressionMap.createAlias({
            type: "other",
            name: relationIdAttribute.junctionAlias,
            metadata: relationIdAttribute.relation.junctionEntityMetadata
        });
    }
    return this;
}

https://github.com/typeorm/typeorm/blob/master/src/query-builder/relation-id/RelationIdAttribute.ts

/**
 * Stores all join relation id attributes which will be used to build a JOIN query.
 */
export class RelationIdAttribute {

    // -------------------------------------------------------------------------
    // Public Properties
    // -------------------------------------------------------------------------

    /**
     * Alias of the joined (destination) table.
     */
    alias?: string;

    /**
     * Name of relation.
     */
    relationName: string;

    /**
     * Property + alias of the object where to joined data should be mapped.
     */
    mapToProperty: string;

    /**
     * Extra condition applied to "ON" section of join.
     */
    queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>;

    /**
     * Indicates if relation id should NOT be loaded as id map.
     */
    disableMixedMap = false;
...

Это немного поздно, но для всех остальных, кто посещает эту страницу, может быть полезно в typeorm есть опция, поэтому мы можем получить результат, который мы хотим.

Другие вопросы по теме