一.postgreSQL 是什么?
1.概念
PostgreSQL 是一个免费、开源、功能完善的对象关系型数据库。他和mysql 一样,都是关系型数据库。
2.postgreSQL 和 mysql 对比

在安装方面
我们使用mysql的时候需要安装 mysql服务端用来存取数据;然后再安装 MYSQL Workbench来图形化查看服务端的数据;如果你在nodejs代码里面操作数据库,你需要安装mysql2包,用代码的方式操作数据库,操作完以后可以在 MYSQL Workbench里面清晰看到数据变化。
和mysql一样,postgreSQL也需要安装三个包,安装 psql 服务端用来存取数据;然后安装 pgAdmin4 来图形化查询服务端的数据;你在nodejs项目里面要用代码操作psql数据库里面的数据,就要安装pg包进行增删改查,然后在pgAdmin4软件里面查看最终数据。
在项目架构方面
在安装方面他们是极其相似的,但是对于aiAgent项目而言,mysql 和 postgresql 之间最大的区别是: postgresql可以存储向量,它还有一个插件pgvector,可以对问题向量和文档向量做余弦相似度检索,找到相关文档,给大模型使用。
mysql虽然也能存储向量,可是他却没有做余弦相似度检索的工具,所以一般在企业里面要是有mysql存数文档,那么就会选择用milvus做向量存储。
当然最新版的milvus也能存储一部分文档块,但是他的能力有限,如果你存的太多,就会将整个milvus的检索向量的能力拉低,所以在企业里面,milvus 里面一般不会放文档块。milvus的优势就是向量相似度对比,那么文档存储就会交给mysql做。所以之前的样例都是mysql + milvus的实现方案。
如果你的项目是一个新项目,没有使用mysql,那么你就可以直接用postgreSQL,他内置的插件pgvector可以快速解决向量相似度检索,从而直接拿到这条数据对应的文本块。而不像 mysql + milvus 一样,先从milvus里面拿到id 然后用这个id 去mysql 里面拿文本块。
在sql语句方面
PostgreSQL 和 MySQL 共享标准 SQL 基础,基本增删改查差异不大;真正明显的差异集中在自增主键、分页简写、日期函数、布尔值、冲突处理、JSON、存储过程、DDL 事务、引号和特有系统函数。
3.运行原理
首先将一个长文本按照某种规则,剪切成文本块,然后由嵌入模型把这个文本块转化成向量,利用
sql语句将 文本块 和 向量 插入到postgreSQL数据库里面。
当用户问问题的时候,嵌入模型会将用户问题转化成向量,然后通过sql语句发送给postgreSQL数据库,再由PostgreSQL配合pgvector计算向量距离并返回最相似的文本块。
pgvector支持多种距离算法,而不仅是余弦相似度,并且检索到的文本还需要拼接到prompt里面交给大模型生成最终回答。

注意:问题向量和文档向量必须使用 同一个嵌入模型生成,否则维度不同、语义空间不同,无法直接比较。
4.安装
4.1 安装postgreSQL











4.2 安装 pgAdmin 4
官网: www.pgadmin.org/download/pg...
pgAdmin 4图形界面的使用和 mysql workbetch 很相似,连接数据库后就能使用sql 语句进行增删改查了。



4.3 在nodejs 里面使用
4.3.1 初始化项目
js
mkdir node-pg-demo
cd node-pg-demo
npm init -y
npm install pg dotenv
4.3.2配置.env
js
PGHOST=localhost
PGPORT=5432
PGUSER=postgres
PGPASSWORD=你的密码
PGDATABASE=node_pg_demo
4.3.3连接数据库
js
import pg from "pg";
import dotenv from "dotenv";
dotenv.config();
const { Pool } = pg;
const pool = new Pool({
host: process.env.PGHOST,
port: process.env.PGPORT,
user: process.env.PGUSER,
password: process.env.PGPASSWORD,
database: process.env.PGDATABASE,
});
// 连接测试
pool.query("SELECT NOW()", (err, res) => {
if (err) {
console.error("连接失败:", err.message);
} else {
console.log("数据库连接成功,服务器时间:", res.rows[0].now);
}
});
export default pool;
4.3.4新建数据表
js
import pool from "./db.js";
const createTable = `
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMPTZ DEFAULT NOW()
)
`;
const run = async () => {
try {
await pool.query(createTable);
console.log("users 表创建成功");
} catch (err) {
console.error("建表失败:", err.message);
} finally {
await pool.end();
}
};
run();
4.3.5增删改查
js
import pool from "./db.js";
// 1. 新增
const createUser = async (name, email, age) => {
const sql = `
INSERT INTO users (name, email, age)
VALUES ($1, $2, $3)
RETURNING *
`;
const res = await pool.query(sql, [name, email, age]);
return res.rows[0];
};
// 2. 查询全部
const getAllUsers = async () => {
const res = await pool.query(
"SELECT * FROM users ORDER BY id DESC"
);
return res.rows;
};
// 3. 按 ID 查询
const getUserById = async (id) => {
const res = await pool.query(
"SELECT * FROM users WHERE id = $1",
[id]
);
return res.rows[0];
};
// 4. 修改
const updateUser = async (id, name, age) => {
const sql = `
UPDATE users
SET name = $1, age = $2
WHERE id = $3
RETURNING *
`;
const res = await pool.query(sql, [name, age, id]);
return res.rows[0];
};
// 5. 删除
const deleteUser = async (id) => {
const res = await pool.query(
"DELETE FROM users WHERE id = $1 RETURNING *",
[id]
);
return res.rows[0];
};
// 演示完整流程
const run = async () => {
try {
// 新增
const user = await createUser("张三", "zhangsan@example.com", 28);
console.log("新增:", user);
// 查询全部
const list = await getAllUsers();
console.log("全部用户:", list);
// 按 ID 查询
const one = await getUserById(user.id);
console.log("单条查询:", one);
// 修改
const updated = await updateUser(user.id, "李四", 30);
console.log("修改后:", updated);
// 删除
const deleted = await deleteUser(user.id);
console.log("已删除:", deleted);
} catch (err) {
console.error("操作失败:", err.message);
} finally {
await pool.end();
}
};
run();
4.4 在nestjs里面使用
4.4.1 初始化项目
js
# 使用 Nest CLI 创建项目
npm i -g @nestjs/cli
nest new nest-pg-demo
cd nest-pg-demo
# 安装 PostgreSQL 驱动和 TypeORM
npm install @nestjs/typeorm typeorm pg
npm install @nestjs/mapped-types
4.4.2 连接数据库
js
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersModule } from './users/users.module';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: '你的密码',
database: 'nest_pg_demo',
autoLoadEntities: true,
synchronize: true, // 开发环境自动建表,生产环境建议关闭
}),
UsersModule,
],
})
export class AppModule {}
4.4.3创建 User 实体(Entity)
新建 src/users/entities/user.entity.ts
js
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
} from 'typeorm';
@Entity('users')
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 100 })
name: string;
@Column({ unique: true, length: 255 })
email: string;
@Column({ nullable: true })
age: number;
@CreateDateColumn()
createdAt: Date;
}
4.4.4创建 DTO(数据传输对象)
新建 src/users/dto/create-user.dto.ts:
typescript
export class CreateUserDto {
name: string;
email: string;
age?: number;
}
新建 src/users/dto/update-user.dto.ts:
scala
import { PartialType } from '@nestjs/mapped-types';
import { CreateUserDto } from './create-user.dto';
export class UpdateUserDto extends PartialType(CreateUserDto) {}
4.4.5创建 Service(业务逻辑 + CRUD)
新建 src/users/users.service.ts:
typescript
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>,
) {}
// 新增
async create(createUserDto: CreateUserDto): Promise<User> {
const user = this.userRepository.create(createUserDto);
return await this.userRepository.save(user);
}
// 查询全部
async findAll(): Promise<User[]> {
return await this.userRepository.find({
order: { id: 'DESC' },
});
}
// 按 ID 查询
async findOne(id: number): Promise<User> {
const user = await this.userRepository.findOne({ where: { id } });
if (!user) {
throw new NotFoundException(`ID 为 ${id} 的用户不存在`);
}
return user;
}
// 修改
async update(id: number, updateUserDto: UpdateUserDto): Promise<User> {
const user = await this.findOne(id);
Object.assign(user, updateUserDto);
return await this.userRepository.save(user);
}
// 删除
async remove(id: number): Promise<void> {
const user = await this.findOne(id);
await this.userRepository.remove(user);
}
}
4.4.6创建 Controller(路由)
新建 src/users/users.controller.ts:
less
import {
Body,
Controller,
Delete,
Get,
Param,
Patch,
Post,
} from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
// POST /users
@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
// GET /users
@Get()
findAll() {
return this.usersService.findAll();
}
// GET /users/:id
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(Number(id));
}
// PATCH /users/:id
@Patch(':id')
update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
return this.usersService.update(Number(id), updateUserDto);
}
// DELETE /users/:id
@Delete(':id')
remove(@Param('id') id: string) {
return this.usersService.remove(Number(id));
}
}
4.4.7 创建 UsersModule
新建 src/users/users.module.ts:
python
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { User } from './entities/user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}