如何在Typeorm中使用queryBuilder优化查询以选择内容?

时间:2019-06-27 11:34:53

标签: typescript typeorm

我有3个实体User,Spot和Thing。 一个用户可以有很多景点,一个景点可以有很多东西。

当前,我正在编写两个查询,一个用于验证该点是否存在于用户中,另一个用于从该点获取事物。 (请参见index.js)。

如何使用createQueryBuilder(而不使用repo.find)编写一个查询,以基于user.idspot.id选择所有内容?我知道有一些加入,但我无法解决。

这是代码的相关部分:

const spot = await spotRepo.createQueryBuilder('spot')
  .innerJoin('spot.user', 'user')
  .where('user.id = :id', { id: 1 })
  .andWhere('spot.id = :id', { id: 1 })
  .getOne();
if (spot !== undefined) {
  console.log(spot);
  console.log('Got the spot');
  const spotWithThings = await spotRepo.createQueryBuilder('spot')
    .leftJoinAndSelect('spot.things', 'things')
    .where('spot.id = :id', { id: spot.id })
    .getOne();
  console.log(spotWithThings);
}

运行该项目的步骤:

  1. git clone https://github.com/fabianmoronzirfas/typeorm-how-to-write-smarter-queries-questionmark.git ./test-repo && cd test-repo
  2. 运行npm i命令
  3. ormconfig.json文件中设置数据库设置
  4. 启动数据库docker-compose up
  5. 运行npm start命令

这是index.ts

import "reflect-metadata";
import { createConnection, getRepository } from "typeorm";
import { User } from "./entity/User";
import { Spot } from './entity/Spot';
import { Thing } from './entity/Thing';

createConnection().then(async connection => {
    {
        console.log("Inserting a new data into the database...");
        const user = new User();
        const spot = new Spot();
        // const things = [];
        for (let i = 0; i < 5; i++) {
            const thing = new Thing();
            if (spot.things === undefined) {
                spot.things = [thing];
            } else {
                spot.things.push(thing);
            }
            await connection.manager.save(thing);;
        }
        user.spots = [spot];
        await connection.manager.save(user);
        await connection.manager.save(spot);
        console.log('setup done');
    }
    const spotRepo = getRepository(Spot);
    const spot = await spotRepo.createQueryBuilder('spot')
    .innerJoin('spot.user', 'user')
    .where('user.id = :id', { id: 1 })
    .andWhere('spot.id = :id', {id: 1})
    .getOne();
    if (spot !== undefined) {
        console.log(spot);
        console.log('Got the spot');
        const spotWithThings = await spotRepo.createQueryBuilder('spot')
        .leftJoinAndSelect('spot.things', 'things')
        .where('spot.id = :id', { id: spot.id })
        .getOne();
        console.log(spotWithThings);
    } else {
        console.log(`No spot? with user id ${1}`);
    }
}).catch(error => console.log(error));

这是Spot.ts

import {Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany} from "typeorm";
import { User } from './User';
import { Thing } from './Thing';
@Entity()
export class Spot {
    @PrimaryGeneratedColumn()
    id: number;
    @ManyToOne( _type => User, user => user.spots)
    public user: User;
    @OneToMany(_type => Thing, (thing) => thing.spot, {
        eager: true,
      })
      public things!: Thing[];
}

这是Thing.ts

import {Entity, PrimaryGeneratedColumn, ManyToOne, JoinColumn} from "typeorm";
import { Spot } from './Spot';

@Entity()
export class Thing {

    @PrimaryGeneratedColumn()
    id: number;

    @ManyToOne( _type => Spot, spot => spot.things , {
        cascade: true,
        // eager: true,
      })
      @JoinColumn()
      public spot!: Spot;
}

这是User.ts

import {Entity, PrimaryGeneratedColumn, OneToMany} from "typeorm";
import { Spot } from './Spot';

@Entity()
export class User {

    @PrimaryGeneratedColumn()
    id: number;
    @OneToMany(_type => Spot, spot => spot.user, {
        cascade: true,
      })
      public spots: Spot[];
}

这是ormconfig.json

{
   "type": "postgres",
   "host": "127.0.0.1",
   "port": 5432,
   "username": "postgres",
   "password": "postgres_password",
   "database": "postgres",
   "synchronize": true,
   "dropSchema": true,
   "logging": false,
   "entities": [
      "src/entity/**/*.ts"
   ],
   "migrations": [
      "src/migration/**/*.ts"
   ],
   "subscribers": [
      "src/subscriber/**/*.ts"
   ],
   "cli": {
      "entitiesDir": "src/entity",
      "migrationsDir": "src/migration",
      "subscribersDir": "src/subscriber"
   }
}

这是我的docker-compose.yml

version: '3'
services:
  postgres:
    container_name: 'pgdb'
    image: 'mdillon/postgis:10'
    ports:
      - '5432:5432'

这是package.json

{
   "name": "typeorm-smarter-req",
   "version": "1.0.0",
   "description": "",
   "main": "index.js",
   "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "start": "ts-node src/index.ts"
   },
   "author": "",
   "license": "ISC",
   "dependencies": {
      "pg": "^7.11.0",
      "reflect-metadata": "^0.1.10",
      "typeorm": "0.2.18"
   },
   "devDependencies": {
      "ts-node": "3.3.0",
      "@types/node": "^8.0.29",
      "typescript": "3.3.3333"
   }
}

这是tsconfig.json

{
   "compilerOptions": {
      "lib": [
         "es5",
         "es6",
         "dom"

      ],
      "target": "es5",
      "module": "commonjs",
      "moduleResolution": "node",
      "outDir": "./build",
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "sourceMap": true
   }
}

1 个答案:

答案 0 :(得分:1)

您想获取东西,所以从Thing回购开始,并询问问题很多,并根据基于联接定义的约束进行过滤:

const thingRepo = entityManager.getRepository(Thing);
const things = thingRepo.createQueryBuilder('thing')
    .leftJoinAndSelect('thing.spot', 'spotThing')
    .leftJoinAndSelect('spotThing.user', 'userSpot')
    .where('spotThing.id = :spotId', {spotId})
    .andWhere('userSpot.id = :userId', {userId})
    .getMany();