ๅฎžไฝ“

ๅฎžไฝ“ๆ˜ฏไป€ไนˆ?

ๅฎžไฝ“ๆ˜ฏไธ€ไธชๆ˜ ๅฐ„ๅˆฐๆ•ฐๆฎๅบ“่กจ๏ผˆๆˆ–ไฝฟ็”จ MongoDB ๆ—ถ็š„้›†ๅˆ๏ผ‰็š„็ฑปใ€‚ ไฝ ๅฏไปฅ้€š่ฟ‡ๅฎšไน‰ไธ€ไธชๆ–ฐ็ฑปๆฅๅˆ›ๅปบไธ€ไธชๅฎžไฝ“๏ผŒๅนถ็”จ@Entity()ๆฅๆ ‡่ฎฐ๏ผš
1
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
2
โ€‹
3
@Entity()
4
export class User {
5
@PrimaryGeneratedColumn()
6
id: number;
7
โ€‹
8
@Column()
9
firstName: string;
10
โ€‹
11
@Column()
12
lastName: string;
13
โ€‹
14
@Column()
15
isActive: boolean;
16
}
Copied!
่ฟ™ๅฐ†ๅˆ›ๅปบไปฅไธ‹ๆ•ฐๆฎๅบ“่กจ๏ผš
1
+-------------+--------------+----------------------------+
2
| user |
3
+-------------+--------------+----------------------------+
4
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
5
| firstName | varchar(255) | |
6
| lastName | varchar(255) | |
7
| isActive | boolean | |
8
+-------------+--------------+----------------------------+
Copied!
ๅŸบๆœฌๅฎžไฝ“็”ฑๅˆ—ๅ’Œๅ…ณ็ณป็ป„ๆˆใ€‚ ๆฏไธชๅฎžไฝ“ๅฟ…้กปๆœ‰ไธ€ไธชไธปๅˆ—๏ผˆๅฆ‚ๆžœไฝฟ็”จ MongoDB๏ผŒๅˆ™ไธบ ObjectId ๅˆ—๏ผ‰ใ€‚
ๆฏไธชๅฎžไฝ“้ƒฝๅฟ…้กปๅœจ่ฟžๆŽฅ้€‰้กนไธญๆณจๅ†Œ๏ผš
1
import { createConnection, Connection } from "typeorm";
2
import { User } from "./entity/User";
3
โ€‹
4
const connection: Connection = await createConnection({
5
type: "mysql",
6
host: "localhost",
7
port: 3306,
8
username: "test",
9
password: "test",
10
database: "test",
11
entities: [User]
12
});
Copied!
ๆˆ–่€…ไฝ ๅฏไปฅๆŒ‡ๅฎšๅŒ…ๅซๆ‰€ๆœ‰ๅฎžไฝ“็š„ๆ•ดไธช็›ฎๅฝ•๏ผŒ ่ฏฅ็›ฎๅฝ•ไธ‹ๆ‰€ๆœ‰ๅฎžไฝ“้ƒฝๅฐ†่ขซๅŠ ่ฝฝ๏ผš
1
import { createConnection, Connection } from "typeorm";
2
โ€‹
3
const connection: Connection = await createConnection({
4
type: "mysql",
5
host: "localhost",
6
port: 3306,
7
username: "test",
8
password: "test",
9
database: "test",
10
entities: ["entity/*.js"]
11
});
Copied!
ๅฆ‚ๆžœ่ฆไธบUserๅฎžไฝ“ไฝฟ็”จๆ›ฟไปฃ่กจๅ๏ผŒๅฏไปฅๅœจ@ EntityไธญๆŒ‡ๅฎš๏ผš@Entity๏ผˆโ€œmy_usersโ€๏ผ‰ใ€‚ ๅฆ‚ๆžœ่ฆไธบๅบ”็”จ็จ‹ๅบไธญ็š„ๆ‰€ๆœ‰ๆ•ฐๆฎๅบ“่กจ่ฎพ็ฝฎๅŸบๆœฌๅ‰็ผ€๏ผŒๅฏไปฅๅœจ่ฟžๆŽฅ้€‰้กนไธญๆŒ‡ๅฎšentityPrefixใ€‚
ไฝฟ็”จๅฎžไฝ“ๆž„้€ ๅ‡ฝๆ•ฐๆ—ถ๏ผŒๅ…ถๅ‚ๆ•ฐๅฟ…้กปๆ˜ฏๅฏ้€‰็š„ใ€‚ ็”ฑไบŽ ORM ๅœจไปŽๆ•ฐๆฎๅบ“ๅŠ ่ฝฝๆ—ถๆ‰ๅˆ›ๅปบๅฎžไฝ“็ฑป็š„ๅฎžไพ‹๏ผŒๅ› ๆญคๅœจๆญคไน‹ๅ‰ๅนถไธ็Ÿฅ้“ๆž„้€ ๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐใ€‚
ๅœจDecorators referenceไธญไบ†่งฃๆœ‰ๅ…ณๅ‚ๆ•ฐ@Entity ็š„ๆ›ดๅคšไฟกๆฏใ€‚

ๅฎžไฝ“ๅˆ—

็”ฑไบŽๆ•ฐๆฎๅบ“่กจ็”ฑๅˆ—็ป„ๆˆ๏ผŒๅ› ๆญคๅฎžไฝ“ไนŸๅฟ…้กป็”ฑๅˆ—็ป„ๆˆใ€‚ ๆ ‡ๆœ‰@ Column็š„ๆฏไธชๅฎžไฝ“็ฑปๅฑžๆ€ง้ƒฝๅฐ†ๆ˜ ๅฐ„ๅˆฐๆ•ฐๆฎๅบ“่กจๅˆ—ใ€‚

ไธปๅˆ—

ๆฏไธชๅฎžไฝ“ๅฟ…้กป่‡ณๅฐ‘ๆœ‰ไธ€ไธชไธปๅˆ—ใ€‚ ๆœ‰ๅ‡ ็ง็ฑปๅž‹็š„ไธป่ฆๅˆ—๏ผš
  • @PrimaryColumn() ๅˆ›ๅปบไธ€ไธชไธปๅˆ—๏ผŒๅฎƒๅฏไปฅ่Žทๅ–ไปปไฝ•็ฑปๅž‹็š„ไปปไฝ•ๅ€ผใ€‚ไฝ ไนŸๅฏไปฅๆŒ‡ๅฎšๅˆ—็ฑปๅž‹ใ€‚ ๅฆ‚ๆžœๆœชๆŒ‡ๅฎšๅˆ—็ฑปๅž‹๏ผŒๅˆ™ๅฐ†ไปŽๅฑžๆ€ง็ฑปๅž‹่‡ชๅŠจๆŽจๆ–ญใ€‚
ไธ‹้ข็š„็คบไพ‹ๅฐ†ไฝฟ็”จint็ฑปๅž‹ๅˆ›ๅปบ id๏ผŒไฝ ๅฟ…้กปๅœจไฟๅญ˜ไน‹ๅ‰ๆ‰‹ๅŠจๅˆ†้…ใ€‚
1
import { Entity, PrimaryColumn } from "typeorm";
2
โ€‹
3
@Entity()
4
export class User {
5
@PrimaryColumn()
6
id: number;
7
}
Copied!
  • @PrimaryGeneratedColumn() ๅˆ›ๅปบไธ€ไธชไธปๅˆ—๏ผŒ่ฏฅๅ€ผๅฐ†ไฝฟ็”จ่‡ชๅŠจๅขž้‡ๅ€ผ่‡ชๅŠจ็”Ÿๆˆใ€‚ ๅฎƒๅฐ†ไฝฟ็”จauto-increment /serial /sequenceๅˆ›ๅปบintๅˆ—๏ผˆๅ–ๅ†ณไบŽๆ•ฐๆฎๅบ“๏ผ‰ใ€‚ ไฝ ไธๅฟ…ๅœจไฟๅญ˜ไน‹ๅ‰ๆ‰‹ๅŠจๅˆ†้…ๅ…ถๅ€ผ๏ผŒ่ฏฅๅ€ผๅฐ†ไผš่‡ชๅŠจ็”Ÿๆˆใ€‚
1
import { Entity, PrimaryGeneratedColumn } from "typeorm";
2
โ€‹
3
@Entity()
4
export class User {
5
@PrimaryGeneratedColumn()
6
id: number;
7
}
Copied!
  • @PrimaryGeneratedColumn("uuid") ๅˆ›ๅปบไธ€ไธชไธปๅˆ—๏ผŒ่ฏฅๅ€ผๅฐ†ไฝฟ็”จuuid่‡ชๅŠจ็”Ÿๆˆใ€‚ Uuid ๆ˜ฏไธ€ไธช็‹ฌ็‰น็š„ๅญ—็ฌฆไธฒ idใ€‚ ไฝ ไธๅฟ…ๅœจไฟๅญ˜ไน‹ๅ‰ๆ‰‹ๅŠจๅˆ†้…ๅ…ถๅ€ผ๏ผŒ่ฏฅๅ€ผๅฐ†่‡ชๅŠจ็”Ÿๆˆใ€‚
1
import { Entity, PrimaryGeneratedColumn } from "typeorm";
2
โ€‹
3
@Entity()
4
export class User {
5
@PrimaryGeneratedColumn("uuid")
6
id: string;
7
}
Copied!
ไฝ ไนŸๅฏไปฅๆ‹ฅๆœ‰ๅคๅˆไธปๅˆ—๏ผš
1
import { Entity, PrimaryColumn } from "typeorm";
2
โ€‹
3
@Entity()
4
export class User {
5
@PrimaryColumn()
6
firstName: string;
7
โ€‹
8
@PrimaryColumn()
9
lastName: string;
10
}
Copied!
ๅฝ“ๆ‚จไฝฟ็”จsaveไฟๅญ˜ๅฎžไฝ“ๆ—ถ๏ผŒๅฎƒๆ€ปๆ˜ฏๅ…ˆๅฐ่ฏ•ไฝฟ็”จ็ป™ๅฎš็š„ๅฎžไฝ“ ID๏ผˆๆˆ– ids๏ผ‰ๅœจๆ•ฐๆฎๅบ“ไธญๆŸฅๆ‰พๅฎžไฝ“ใ€‚ ๅฆ‚ๆžœๆ‰พๅˆฐ id / ids๏ผŒๅˆ™ๅฐ†ๆ›ดๆ–ฐๆ•ฐๆฎๅบ“ไธญ็š„่ฟ™ไธ€่กŒใ€‚ ๅฆ‚ๆžœๆฒกๆœ‰ๅŒ…ๅซ id / ids ็š„่กŒ๏ผŒๅˆ™ไผšๆ’ๅ…ฅไธ€ไธชๆ–ฐ่กŒใ€‚
่ฆ้€š่ฟ‡ id ๆŸฅๆ‰พๅฎžไฝ“๏ผŒๅฏไปฅไฝฟ็”จmanager.findOneๆˆ–repository.findOneใ€‚ ไพ‹๏ผš
1
// ไฝฟ็”จๅ•ไธชไธป้”ฎๆŸฅๆ‰พไธ€ไธชid
2
const person = await connection.manager.findOne(Person, 1);
3
const person = await connection.getRepository(Person).findOne(1);
4
โ€‹
5
// ไฝฟ็”จๅคๅˆไธป้”ฎๆ‰พๅˆฐไธ€ไธชid
6
const user = await connection.manager.findOne(User, { firstName: "Timber", lastName: "Saw" });
7
const user = await connection.getRepository(User).findOne({ firstName: "Timber", lastName: "Saw" });
Copied!

็‰นๆฎŠๅˆ—

ๆœ‰ๅ‡ ็ง็‰นๆฎŠ็š„ๅˆ—็ฑปๅž‹ๅฏไปฅไฝฟ็”จ๏ผš
  • @CreateDateColumn ๆ˜ฏไธ€ไธช็‰นๆฎŠๅˆ—๏ผŒ่‡ชๅŠจไธบๅฎžไฝ“ๆ’ๅ…ฅๆ—ฅๆœŸใ€‚ๆ— ้œ€่ฎพ็ฝฎๆญคๅˆ—๏ผŒ่ฏฅๅ€ผๅฐ†่‡ชๅŠจ่ฎพ็ฝฎใ€‚
  • @UpdateDateColumn ๆ˜ฏไธ€ไธช็‰นๆฎŠๅˆ—๏ผŒๅœจๆฏๆฌก่ฐƒ็”จๅฎžไฝ“็ฎก็†ๅ™จๆˆ–ๅญ˜ๅ‚จๅบ“็š„saveๆ—ถ๏ผŒ่‡ชๅŠจๆ›ดๆ–ฐๅฎžไฝ“ๆ—ฅๆœŸใ€‚ๆ— ้œ€่ฎพ็ฝฎๆญคๅˆ—๏ผŒ่ฏฅๅ€ผๅฐ†่‡ชๅŠจ่ฎพ็ฝฎใ€‚
  • @VersionColumn ๆ˜ฏไธ€ไธช็‰นๆฎŠๅˆ—๏ผŒๅœจๆฏๆฌก่ฐƒ็”จๅฎžไฝ“็ฎก็†ๅ™จๆˆ–ๅญ˜ๅ‚จๅบ“็š„saveๆ—ถ่‡ชๅŠจๅขž้•ฟๅฎžไฝ“็‰ˆๆœฌ๏ผˆๅขž้‡็ผ–ๅท๏ผ‰ใ€‚ๆ— ้œ€่ฎพ็ฝฎๆญคๅˆ—๏ผŒ่ฏฅๅ€ผๅฐ†่‡ชๅŠจ่ฎพ็ฝฎใ€‚

็ฉบ้—ดๅˆ—

MS SQL๏ผŒMySQL/MariaDB ๅ’Œ PostgreSQL ้ƒฝๆ”ฏๆŒ Spatial ๅˆ—ใ€‚็”ฑไบŽๅ„ๆ•ฐๆฎๅบ“ๅˆ—ๅไธๅŒ๏ผŒTypeORM ๅฏนๆ•ฐๆฎๅบ“็š„ๆ”ฏๆŒ็•ฅๆœ‰ๅทฎๅผ‚ใ€‚
MS SQL ๅ’Œ MySQL/MariaDB ็š„ TypeORM ๆ”ฏๆŒwell-known text(WKT)็š„ geometries๏ผŒๅ› ๆญค geometry ๅˆ— ๅบ”่ฏฅๆ˜ฏ็”จstring็ฑปๅž‹ๆ ‡่ฎฐใ€‚
TypeORM ็š„ PostgreSQL ๆ”ฏๆŒไฝฟ็”จGeoJSONไฝœไธบไบคๆขๆ ผๅผ๏ผŒๅ› ๆญค geometry ๅˆ—ๅบ”ๅœจๅฏผๅ…ฅๅŽๆ ‡่ฎฐไธบobjectๆˆ–Geometry๏ผˆๆˆ–ๅญ็ฑป๏ผŒไพ‹ๅฆ‚Point๏ผ‰ใ€‚
TypeORMๅฐ่ฏ•ๅšๆญฃ็กฎ็š„ไบ‹ๆƒ…๏ผŒไฝ†ๅนถไธๆ€ปๆ˜ฏ่ƒฝๅคŸ็กฎๅฎšไฝ•ๆ—ถๆ’ๅ…ฅ็š„ๅ€ผๆˆ–PostGISๅ‡ฝๆ•ฐ็š„็ป“ๆžœๅบ”่ขซ่ง†ไธบๅ‡ ไฝ•ใ€‚ ๅ› ๆญค๏ผŒไฝ ๅฏ่ƒฝไผšๅ‘็Žฐ่‡ชๅทฑ็ผ–ๅ†™็š„ไปฃ็ ็ฑปไผผไบŽไปฅไธ‹ไปฃ็ ๏ผŒๅ…ถไธญๅ€ผไปŽGeoJSON่ฝฌๆขไธบPostGIS geometry,ๅนถไฝœไธบjson่ฝฌๆขไธบGeoJSON๏ผš
1
const origin = {
2
type: "Point",
3
coordinates: [0, 0]
4
};
5
โ€‹
6
await getManager()
7
.createQueryBuilder(Thing, "thing")
8
// ๅฐ†ๅญ—็ฌฆไธฒๅŒ–็š„GeoJSON่ฝฌๆขไธบๅ…ทๆœ‰ไธŽ่กจ่ง„่ŒƒๅŒน้…็š„SRID็š„geometry
9
.where("ST_Distance(geom, ST_SetSRID(ST_GeomFromGeoJSON(:origin), ST_SRID(geom))) > 0")
10
.orderBy({
11
"ST_Distance(geom, ST_SetSRID(ST_GeomFromGeoJSON(:origin), ST_SRID(geom)))": {
12
order: "ASC"
13
}
14
})
15
.setParameters({
16
// ๅญ—็ฌฆไธฒๅŒ– GeoJSON
17
origin: JSON.stringify(origin)
18
})
19
.getMany();
20
โ€‹
21
await getManager()
22
.createQueryBuilder(Thing, "thing")
23
// ๅฐ†geometry็ป“ๆžœ่ฝฌๆขไธบGeoJSON๏ผŒไปฅๅฐ†ๆญค่ง†ไธบJSON๏ผˆไปฅไพฟTypeORM็Ÿฅ้“ๅๅบๅˆ—ๅŒ–ๅฎƒ๏ผ‰
24
.select("ST_AsGeoJSON(ST_Buffer(geom, 0.1))::json geom")
25
.from("thing")
26
.getMany();
Copied!

ๅˆ—็ฑปๅž‹

TypeORM ๆ”ฏๆŒๆ‰€ๆœ‰ๆœ€ๅธธ็”จ็š„ๆ•ฐๆฎๅบ“ๆ”ฏๆŒ็š„ๅˆ—็ฑปๅž‹ใ€‚ ๅˆ—็ฑปๅž‹ๆ˜ฏ็‰นๅฎšไบŽๆ•ฐๆฎๅบ“็ฑปๅž‹็š„ - ่ฟ™ไธบๆ•ฐๆฎๅบ“ๆžถๆž„ๆไพ›ไบ†ๆ›ดๅคง็š„็ตๆดปๆ€งใ€‚ ไฝ ๅฏไปฅๅฐ†ๅˆ—็ฑปๅž‹ๆŒ‡ๅฎšไธบ@ Column็š„็ฌฌไธ€ไธชๅ‚ๆ•ฐ ๆˆ–่€…ๅœจ@Column็š„ๅˆ—้€‰้กนไธญๆŒ‡ๅฎš๏ผŒไพ‹ๅฆ‚๏ผš
1
@Column("int")
Copied!
ๆˆ–
1
@Column({ type: "int" })
Copied!
ๅฆ‚ๆžœ่ฆๆŒ‡ๅฎšๅ…ถไป–็ฑปๅž‹ๅ‚ๆ•ฐ๏ผŒๅฏไปฅ้€š่ฟ‡ๅˆ—้€‰้กนๆฅๆ‰ง่กŒใ€‚ ไพ‹ๅฆ‚:
1
@Column("varchar", { length: 200 })
Copied!
ๆˆ–
1
@Column({ type: "int", length: 200 })
Copied!

mysql/mariadb็š„ๅˆ—็ฑปๅž‹

int, tinyint, smallint, mediumint, bigint, float, double, dec, decimal, numeric, date, datetime, timestamp, time, year, char, varchar, nvarchar, text, tinytext, mediumtext, blob, longtext, tinyblob, mediumblob, longblob, enum, json, binary, geometry, point, linestring, polygon, multipoint, multilinestring, multipolygon, geometrycollection

postgres็š„ๅˆ—็ฑปๅž‹

int, int2, int4, int8, smallint, integer, bigint, decimal, numeric, real, float, float4, float8, double precision, money, character varying, varchar, character, char, text, citext, hstore, bytea, bit, varbit, bit varying, timetz, timestamptz, timestamp, timestamp without time zone, timestamp with time zone, date, time, time without time zone, time with time zone, interval, bool, boolean, enum, point, line, lseg, box, path, polygon, circle, cidr, inet, macaddr, tsvector, tsquery, uuid, xml, json, jsonb, int4range, int8range, numrange, tsrange, tstzrange, daterange, geometry, geography

sqlite/cordova/react-native/expo็š„ๅˆ—็ฑปๅž‹

int, int2, int8, integer, tinyint, smallint, mediumint, bigint, decimal, numeric, float, double, real, double precision, datetime, varying character, character, native character, varchar, nchar, nvarchar2, unsigned big int, boolean, blob, text, clob, date

mssql็š„ๅˆ—็ฑปๅž‹

int, bigint, bit, decimal, money, numeric, smallint, smallmoney, tinyint, float, real, date, datetime2, datetime, datetimeoffset, smalldatetime, time, char, varchar, text, nchar, nvarchar, ntext, binary, image, varbinary, hierarchyid, sql_variant, timestamp, uniqueidentifier, xml, geometry, geography, rowversion

oracle็š„ๅˆ—็ฑปๅž‹

char, nchar, nvarchar2, varchar2, long, raw, long raw, number, numeric, float, dec, decimal, integer, int, smallint, real, double precision, date, timestamp, timestamp with time zone, timestamp with local time zone, interval year to month, interval day to second, bfile, blob, clob, nclob, rowid, urowid

enum ๅˆ—็ฑปๅž‹

postgresๅ’Œmysql้ƒฝๆ”ฏๆŒenumๅˆ—็ฑปๅž‹ใ€‚ ๅนถๆœ‰ๅคš็งๅˆ—ๅฎšไน‰ๆ–นๅผ๏ผš
ไฝฟ็”จtypescriptๆžšไธพ๏ผš
1
export enum UserRole {
2
ADMIN = "admin",
3
EDITOR = "editor",
4
GHOST = "ghost"
5
}
6
โ€‹
7
@Entity()
8
export class User {
9
โ€‹
10
@PrimaryGeneratedColumn()
11
id: number;
12
โ€‹
13
@Column({
14
type: "enum",
15
enum: UserRole,
16
default: UserRole.GHOST
17
})
18
role: UserRole
19
โ€‹
20
}
Copied!
ๆณจๆ„๏ผšๆ”ฏๆŒๅญ—็ฌฆไธฒ๏ผŒๆ•ฐๅญ—ๅ’Œๅผ‚ๆž„ๆžšไธพใ€‚
ไฝฟ็”จๅธฆๆžšไธพๅ€ผ็š„ๆ•ฐ็ป„๏ผš
1
export type UserRoleType = "admin" | "editor" | "ghost",
2
โ€‹
3
@Entity()
4
export class User {
5
โ€‹
6
@PrimaryGeneratedColumn()
7
id: number;
8
โ€‹
9
@Column({
10
type: "enum",
11
enum: ["admin", "editor", "ghost"],
12
default: "ghost"
13
})
14
role: UserRoleType
15
}
Copied!

simple-array็š„ๅˆ—็ฑปๅž‹

ๆœ‰ไธ€็ง็งฐไธบsimple-array็š„็‰นๆฎŠๅˆ—็ฑปๅž‹๏ผŒๅฎƒๅฏไปฅๅฐ†ๅŽŸๅง‹ๆ•ฐ็ป„ๅ€ผๅญ˜ๅ‚จๅœจๅ•ไธชๅญ—็ฌฆไธฒๅˆ—ไธญใ€‚ ๆ‰€ๆœ‰ๅ€ผ้ƒฝไปฅ้€—ๅทๅˆ†้š”ใ€‚ ไพ‹ๅฆ‚๏ผš
1
@Entity()
2
export class User {
3
@PrimaryGeneratedColumn()
4
id: number;
5
โ€‹
6
@Column("simple-array")
7
names: string[];
8
}
Copied!
1
const user = new User();
2
user.names = ["Alexander", "Alex", "Sasha", "Shurik"];
Copied!
ๅญ˜ๅ‚จๅœจๅ•ไธชๆ•ฐๆฎๅบ“ๅˆ—ไธญ็š„Alexander๏ผŒAlex๏ผŒSasha๏ผŒShurikๅ€ผใ€‚ ๅฝ“ไฝ ไปŽๆ•ฐๆฎๅบ“ๅŠ ่ฝฝๆ•ฐๆฎๆ—ถ๏ผŒname ๅฐ†ไฝœไธบ names ๆ•ฐ็ป„่ฟ”ๅ›ž๏ผŒๅฐฑๅƒไน‹ๅ‰ๅญ˜ๅ‚จๅฎƒไปฌไธ€ๆ ทใ€‚
ๆณจๆ„ไธ่ƒฝๅœจๅ€ผ้‡Œ้ขๆœ‰ไปปไฝ•้€—ๅทใ€‚

simple-json ๅˆ—็ฑปๅž‹

่ฟ˜ๆœ‰ไธ€ไธชๅไธบsimple-json็š„็‰นๆฎŠๅˆ—็ฑปๅž‹๏ผŒๅฎƒๅฏไปฅๅญ˜ๅ‚จไปปไฝ•ๅฏไปฅ้€š่ฟ‡ JSON.stringify ๅญ˜ๅ‚จๅœจๆ•ฐๆฎๅบ“ไธญ็š„ๅ€ผใ€‚ ๅฝ“ไฝ ็š„ๆ•ฐๆฎๅบ“ไธญๆฒกๆœ‰ json ็ฑปๅž‹่€Œไฝ ๅˆๆƒณๅญ˜ๅ‚จๅ’ŒๅŠ ่ฝฝๅฏน่ฑก๏ผŒ่ฏฅ็ฑปๅž‹ๅฐฑๅพˆๆœ‰็”จไบ†ใ€‚ ไพ‹ๅฆ‚:
1
@Entity()
2
export class User {
3
@PrimaryGeneratedColumn()
4
id: number;
5
โ€‹
6
@Column("simple-json")
7
profile: { name: string; nickname: string };
8
}
Copied!
1
const user = new User();
2
user.profile = { name: "John", nickname: "Malkovich" };
Copied!
ๅญ˜ๅ‚จๅœจๅ•ไธชๆ•ฐๆฎๅบ“ๅˆ—ไธญ็š„{โ€œnameโ€๏ผšโ€œJohnโ€๏ผŒโ€œnicknameโ€๏ผšโ€œMalkovichโ€}ๅ€ผ ๅฝ“ไฝ ไปŽๆ•ฐๆฎๅบ“ๅŠ ่ฝฝๆ•ฐๆฎๆ—ถ๏ผŒๅฐ†้€š่ฟ‡ JSON.parse ่ฟ”ๅ›ž object/array/primitiveใ€‚

ๅ…ทๆœ‰็”Ÿๆˆๅ€ผ็š„ๅˆ—

ไฝ ๅฏไปฅไฝฟ็”จ@Generated่ฃ…้ฅฐๅ™จๅˆ›ๅปบๅ…ทๆœ‰็”Ÿๆˆๅ€ผ็š„ๅˆ—ใ€‚ ไพ‹ๅฆ‚๏ผš
1
@Entity()
2
export class User {
3
@PrimaryColumn()
4
id: number;
5
โ€‹
6
@Column()
7
@Generated("uuid")
8
uuid: string;
9
}
Copied!
uuidๅ€ผๅฐ†่‡ชๅŠจ็”Ÿๆˆๅนถๅญ˜ๅ‚จๅˆฐๆ•ฐๆฎๅบ“ไธญใ€‚
้™คไบ†"uuid"ไน‹ๅค–๏ผŒ่ฟ˜ๆœ‰"increment"็”Ÿๆˆ็ฑปๅž‹๏ผŒไฝ†ๆ˜ฏๅฏนไบŽ่ฟ™็ง็ฑปๅž‹็š„็”Ÿๆˆ๏ผŒๆŸไบ›ๆ•ฐๆฎๅบ“ๅนณๅฐๅญ˜ๅœจไธ€ไบ›้™ๅˆถ๏ผˆไพ‹ๅฆ‚๏ผŒๆŸไบ›ๆ•ฐๆฎๅบ“ๅช่ƒฝๆœ‰ไธ€ไธชๅขž้‡ๅˆ—๏ผŒๆˆ–่€…ๅ…ถไธญไธ€ไบ›้œ€่ฆๅขž้‡ๆ‰่ƒฝๆˆไธบไธป้”ฎ๏ผ‰ใ€‚

ๅˆ—้€‰้กน

ๅˆ—้€‰้กนๅฎšไน‰ๅฎžไฝ“ๅˆ—็š„ๅ…ถไป–้€‰้กนใ€‚ ไฝ ๅฏไปฅๅœจ@ ColumnไธŠๆŒ‡ๅฎšๅˆ—้€‰้กน๏ผš
1
@Column({
2
type: "varchar",
3
length: 150,
4
unique: true,
5
// ...
6
})
7
name: string;
Copied!
ColumnOptionsไธญๅฏ็”จ้€‰้กนๅˆ—่กจ๏ผš
  • type: ColumnType - ๅˆ—็ฑปๅž‹ใ€‚ๅ…ถไธญไน‹ไธ€ๅœจไธŠ้ข.
  • name: string - ๆ•ฐๆฎๅบ“่กจไธญ็š„ๅˆ—ๅใ€‚
้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒๅˆ—ๅ็งฐๆ˜ฏไปŽๅฑžๆ€ง็š„ๅ็งฐ็”Ÿๆˆ็š„ใ€‚ ไฝ ไนŸๅฏไปฅ้€š่ฟ‡ๆŒ‡ๅฎš่‡ชๅทฑ็š„ๅ็งฐๆฅๆ›ดๆ”นๅฎƒใ€‚
  • length: number - ๅˆ—็ฑปๅž‹็š„้•ฟๅบฆใ€‚ ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœ่ฆๅˆ›ๅปบvarchar๏ผˆ150๏ผ‰็ฑปๅž‹๏ผŒ่ฏทๆŒ‡ๅฎšๅˆ—็ฑปๅž‹ๅ’Œ้•ฟๅบฆ้€‰้กนใ€‚
  • width: number - ๅˆ—็ฑปๅž‹็š„ๆ˜พ็คบ่Œƒๅ›ดใ€‚ ไป…็”จไบŽMySQL integer typesโ€‹
  • onUpdate: string - ON UPDATE่งฆๅ‘ๅ™จใ€‚ ไป…็”จไบŽ MySQL.
  • nullable: boolean - ๅœจๆ•ฐๆฎๅบ“ไธญไฝฟๅˆ—NULLๆˆ–NOT NULLใ€‚ ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒๅˆ—ๆ˜ฏnullable๏ผšfalseใ€‚
  • update: boolean - ๆŒ‡็คบ"save"ๆ“ไฝœๆ˜ฏๅฆๆ›ดๆ–ฐๅˆ—ๅ€ผใ€‚ๅฆ‚ๆžœไธบfalse๏ผŒๅˆ™ๅช่ƒฝๅœจ็ฌฌไธ€ๆฌกๆ’ๅ…ฅๅฏน่ฑกๆ—ถ็ผ–ๅ†™่ฏฅๅ€ผใ€‚ ้ป˜่ฎคๅ€ผไธบ"true"ใ€‚
  • select: boolean - ๅฎšไน‰ๅœจ่ฟ›่กŒๆŸฅ่ฏขๆ—ถๆ˜ฏๅฆ้ป˜่ฎค้š่—ๆญคๅˆ—ใ€‚ ่ฎพ็ฝฎไธบfalseๆ—ถ๏ผŒๅˆ—ๆ•ฐๆฎไธไผšๆ˜พ็คบๆ ‡ๅ‡†ๆŸฅ่ฏขใ€‚ ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒๅˆ—ๆ˜ฏselect๏ผštrue
  • default: string - ๆทปๅŠ ๆ•ฐๆฎๅบ“็บงๅˆ—็š„DEFAULTๅ€ผใ€‚
  • primary: boolean - ๅฐ†ๅˆ—ๆ ‡่ฎฐไธบไธป่ฆๅˆ—ใ€‚ ไฝฟ็”จๆ–นๅผๅ’Œ@ PrimaryColumn็›ธๅŒใ€‚
  • unique: boolean - ๅฐ†ๅˆ—ๆ ‡่ฎฐไธบๅ”ฏไธ€ๅˆ—๏ผˆๅˆ›ๅปบๅ”ฏไธ€็บฆๆŸ๏ผ‰ใ€‚
  • comment: string - ๆ•ฐๆฎๅบ“ๅˆ—ๅค‡ๆณจ๏ผŒๅนถ้žๆ‰€ๆœ‰ๆ•ฐๆฎๅบ“็ฑปๅž‹้ƒฝๆ”ฏๆŒใ€‚
  • precision: number - ๅ่ฟ›ๅˆถ๏ผˆ็ฒพ็กฎๆ•ฐๅญ—๏ผ‰ๅˆ—็š„็ฒพๅบฆ๏ผˆไป…้€‚็”จไบŽๅ่ฟ›ๅˆถๅˆ—๏ผ‰๏ผŒ่ฟ™ๆ˜ฏไธบๅ€ผๅญ˜ๅ‚จ็š„ๆœ€ๅคงไฝๆ•ฐใ€‚ไป…็”จไบŽๆŸไบ›ๅˆ—็ฑปๅž‹ใ€‚
  • scale: number - ๅ่ฟ›ๅˆถ๏ผˆ็ฒพ็กฎๆ•ฐๅญ—๏ผ‰ๅˆ—็š„ๆฏ”ไพ‹๏ผˆไป…้€‚็”จไบŽๅ่ฟ›ๅˆถๅˆ—๏ผ‰๏ผŒ่กจ็คบๅฐๆ•ฐ็‚นๅณไพง็š„ไฝๆ•ฐ๏ผŒไธ”ไธๅพ—ๅคงไบŽ็ฒพๅบฆใ€‚ ไป…็”จไบŽๆŸไบ›ๅˆ—็ฑปๅž‹ใ€‚
  • zerofill: boolean - ๅฐ†ZEROFILLๅฑžๆ€ง่ฎพ็ฝฎไธบๆ•ฐๅญ—ๅˆ—ใ€‚ ไป…ๅœจ MySQL ไธญไฝฟ็”จใ€‚ ๅฆ‚ๆžœๆ˜ฏtrue๏ผŒMySQL ไผš่‡ชๅŠจๅฐ†UNSIGNEDๅฑžๆ€งๆทปๅŠ ๅˆฐๆญคๅˆ—ใ€‚
  • unsigned: boolean - ๅฐ†UNSIGNEDๅฑžๆ€ง่ฎพ็ฝฎไธบๆ•ฐๅญ—ๅˆ—ใ€‚ ไป…ๅœจ MySQL ไธญไฝฟ็”จใ€‚
  • charset: string - ๅฎšไน‰ๅˆ—ๅญ—็ฌฆ้›†ใ€‚ ๅนถ้žๆ‰€ๆœ‰ๆ•ฐๆฎๅบ“็ฑปๅž‹้ƒฝๆ”ฏๆŒใ€‚
  • collation: string - ๅฎšไน‰ๅˆ—ๆŽ’ๅบ่ง„ๅˆ™ใ€‚
  • enum: string[]|AnyEnum - ๅœจenumๅˆ—็ฑปๅž‹ไธญไฝฟ็”จ๏ผŒไปฅๆŒ‡ๅฎšๅ…่ฎธ็š„ๆžšไธพๅ€ผๅˆ—่กจใ€‚ ไฝ ไนŸๅฏไปฅๆŒ‡ๅฎšๆ•ฐ็ป„ๆˆ–ๆŒ‡ๅฎšๆžšไธพ็ฑปใ€‚
  • asExpression: string - ็”Ÿๆˆ็š„ๅˆ—่กจ่พพๅผใ€‚ ไป…ๅœจMySQLไธญไฝฟ็”จใ€‚
  • generatedType: "VIRTUAL"|"STORED" - ็”Ÿๆˆ็š„ๅˆ—็ฑปๅž‹ใ€‚ ไป…ๅœจMySQLไธญไฝฟ็”จใ€‚
  • hstoreType: "object"|"string" -่ฟ”ๅ›žHSTOREๅˆ—็ฑปๅž‹ใ€‚ ไปฅๅญ—็ฌฆไธฒๆˆ–ๅฏน่ฑก็š„ๅฝขๅผ่ฟ”ๅ›žๅ€ผใ€‚ ไป…ๅœจPostgresไธญไฝฟ็”จใ€‚
  • array: boolean - ็”จไบŽๅฏไปฅๆ˜ฏๆ•ฐ็ป„็š„ postgres ๅˆ—็ฑปๅž‹๏ผˆไพ‹ๅฆ‚ int []๏ผ‰
  • transformer: { from(value: DatabaseType): EntityType, to(value: EntityType): DatabaseType } - ็”จไบŽๅฐ†ไปปๆ„็ฑปๅž‹EntityType็š„ๅฑžๆ€ง็ผ–็ป„ไธบๆ•ฐๆฎๅบ“ๆ”ฏๆŒ็š„็ฑปๅž‹DatabaseTypeใ€‚
ๆณจๆ„๏ผšๅคงๅคšๆ•ฐๅˆ—้€‰้กน้ƒฝๆ˜ฏ็‰นๅฎšไบŽ RDBMS ็š„๏ผŒๅนถไธ”ๅœจMongoDBไธญไธๅฏ็”จใ€‚

ๅฎžไฝ“็ปงๆ‰ฟ

ไฝ ๅฏไปฅไฝฟ็”จๅฎžไฝ“็ปงๆ‰ฟๅ‡ๅฐ‘ไปฃ็ ไธญ็š„้‡ๅคใ€‚
ไพ‹ๅฆ‚๏ผŒไฝ ๆœ‰Photo, Question, Post ไธ‰ไธชๅฎžไฝ“:
1
@Entity()
2
export class Photo {
3
@PrimaryGeneratedColumn()
4
id: number;
5
โ€‹
6
@Column()
7
title: string;
8
โ€‹
9
@Column()
10
description: string;
11
โ€‹
12
@Column()
13
size: string;
14
}
15
โ€‹
16
@Entity()
17
export class Question {
18
@PrimaryGeneratedColumn()
19
id: number;
20
โ€‹
21
@Column()
22
title: string;
23
โ€‹
24
@Column()
25
description: string;
26
โ€‹
27
@Column()
28
answersCount: number;
29
}
30
โ€‹
31
@Entity()
32
export class Post {
33
@PrimaryGeneratedColumn()
34
id: number;
35
โ€‹
36
@Column()
37
title: string;
38
โ€‹
39
@Column()
40
description: string;
41
โ€‹
42
@Column()
43
viewCount: number;
44
}
Copied!
ๆญฃๅฆ‚ไฝ ๆ‰€็œ‹ๅˆฐ็š„๏ผŒๆ‰€ๆœ‰่ฟ™ไบ›ๅฎžไฝ“้ƒฝๆœ‰ๅ…ฑๅŒ็š„ๅˆ—๏ผšid๏ผŒtitle๏ผŒdescriptionใ€‚ ไธบไบ†ๅ‡ๅฐ‘้‡ๅคๅนถไบง็”Ÿๆ›ดๅฅฝ็š„ๆŠฝ่ฑก๏ผŒๆˆ‘ไปฌๅฏไปฅไธบๅฎƒไปฌๅˆ›ๅปบไธ€ไธชๅไธบContent็š„ๅŸบ็ฑป๏ผš
1
export abstract class Content {
2
@PrimaryGeneratedColumn()
3
id: number;
4
โ€‹
5
@Column()
6
title: string;
7
โ€‹
8
@Column()
9
description: string;
10
}
11
@Entity()
12
export class Photo extends Content {
13
@Column()
14
size: string;
15
}
16
โ€‹
17
@Entity()
18
export class Question extends Content {
19
@Column()
20
answersCount: number;
21
}
22
โ€‹
23
@Entity()
24
export class Post extends Content {
25
@Column()
26
viewCount: number;
27
}
Copied!
ๆฅ่‡ช็ˆถๅฎžไฝ“็š„ๆ‰€ๆœ‰ๅˆ—๏ผˆrelations๏ผŒembeds ็ญ‰๏ผ‰๏ผˆ็ˆถ็บงไนŸๅฏไปฅๆ‰ฉๅฑ•ๅ…ถไป–ๅฎžไฝ“๏ผ‰ๅฐ†ๅœจๆœ€็ปˆๅฎžไฝ“ไธญ็ปงๆ‰ฟๅ’Œๅˆ›ๅปบใ€‚

ๆ ‘ๅฎžไฝ“

TypeORM ๆ”ฏๆŒๅญ˜ๅ‚จๆ ‘็ป“ๆž„็š„ Adjacency ๅˆ—่กจๅ’Œ Closure ่กจๆจกๅผใ€‚

้‚ปๆŽฅๅˆ—่กจ

้‚ปๆŽฅๅˆ—่กจๆ˜ฏไธ€ไธชๅ…ทๆœ‰่‡ชๅผ•็”จ็š„็ฎ€ๅ•ๆจกๅž‹ใ€‚ ่ฟ™็งๆ–นๆณ•็š„ๅฅฝๅค„ๆ˜ฏ็ฎ€ๅ•๏ผŒ็ผบ็‚นๆ˜ฏไฝ ไธ่ƒฝๅ› ไธบ่ฟžๆŽฅ้™ๅˆถ่€Œ็ซ‹ๅˆปๅŠ ่ฝฝไธ€ไธชๆ ‘ๅฎžไฝ“ใ€‚
ไพ‹ๅฆ‚:
1
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne, OneToMany } from "typeorm";
2
โ€‹
3
@Entity()
4
export class Category {
5
@PrimaryGeneratedColumn()
6
id: number;
7
โ€‹
8
@Column()
9
name: string;
10
โ€‹
11
@Column()
12
description: string;
13
โ€‹
14
@OneToMany(type => Category, category => category.children)
15
parent: Category;
16
โ€‹
17
@ManyToOne(type => Category, category => category.parent)
18
children: Category;
19
}
Copied!

Closure ่กจ

closure ่กจไปฅ็‰นๆฎŠๆ–นๅผๅœจๅ•็‹ฌ็š„่กจไธญๅญ˜ๅ‚จ็ˆถๅ’Œๅญไน‹้—ด็š„ๅ…ณ็ณปใ€‚ ๅฎƒๅœจ่ฏปๅ†™ๆ–น้ข้ƒฝๅพˆๆœ‰ๆ•ˆใ€‚
่ฆไบ†่งฃๆœ‰ๅ…ณ closure ่กจ็š„ๆ›ดๅคšไฟกๆฏ๏ผŒ่ฏทๆŸฅ็œ‹ this awesome presentation by Bill Karwin.
ไพ‹ๅฆ‚:
1
import { Entity, Tree, Column, PrimaryGeneratedColumn, TreeChildren, TreeParent, TreeLevelColumn } from "typeorm";
2
โ€‹
3
@Entity()
4
@Tree("closure-table")
5
export class Category {
6
@PrimaryGeneratedColumn()
7
id: number;
8
โ€‹
9
@Column()
10
name: string;
11
โ€‹
12
@Column()
13
description: string;
14
โ€‹
15
@TreeChildren()
16
children: Category;
17
โ€‹
18
@TreeParent()
19
parent: Category;
20
โ€‹
21
@TreeLevelColumn()
22
level: number;
23
}
Copied!
Last modified 1mo ago