Repository-学习指南_小白版

Base/Repository 包详解------小白也能看懂

📍 原文位置:D:\AI0409\Day22\Repository-学习指南.md

本文档的目标:让完全不懂数据库操作的小白也能理解这个包在做什么、怎么用、为什么这样设计。


前置知识:在看这个之前,你需要知道......

🗄️ 数据库是什么

数据库 = 专门存数据的仓库,就像一个超级强大的 Excel:

复制代码
Excel 表格:
┌──────┬───────┬───────┐
│ ID   │ 姓名   │ 年龄  │
├──────┼───────┼───────┤
│ 1    │ 张三   │ 25    │
│ 2    │ 李四   │ 30    │
│ 3    │ 王五   │ 28    │
└──────┴───────┴───────┘

数据库表(程序看到的):
同样的结构,但可以:
  - 存储**百万、千万、甚至上亿条**数据
  - 一秒钟查询**几千条**记录
  - 支持**多人同时访问**
  - **不会像 Excel 那样卡死**

📝 SQL 是什么

SQL = 和数据库对话的语言。

sql 复制代码
-- 查所有用户
SELECT * FROM users;

-- 查年龄大于25的用户
SELECT * FROM users WHERE age > 25;

-- 插入新用户
INSERT INTO users (name, age) VALUES ('赵六', 22);

-- 更新用户年龄
UPDATE users SET age = 26 WHERE name = '张三';

-- 删除用户
DELETE FROM users WHERE name = '王五';

问题来了:每次都要写 SQL 很麻烦,而且容易写错!

🔧 Repository 包解决了什么问题

不用写 SQL,用 Python 代码就能操作数据库。

python 复制代码
# ❌ 传统方式:手动写 SQL
cursor.execute("SELECT * FROM users WHERE id = 1")
user = cursor.fetchone()

# ✅ Repository 方式:像操作 Python 对象一样操作数据库
user = User.get_by_id(1)  # 一行搞定!

第1步:理解分层架构------这是理解一切的钥匙

🏠 生活类比:餐厅吃饭

复制代码
你(顾客)
    │
    │ "我要一份宫保鸡丁"
    ▼
服务员(接单员)
    │
    │ "好的,记下了"
    │
    ▼
厨房(厨师)
    │
    │ 实际炒菜
    ▼
菜品端上桌

对应到数据库操作:

复制代码
┌─────────────────────────────────────┐
│  模型层 (Model Layer)                 │  ← 你写代码直接打交道的
│  User.save()  User.get_by_id(1)      │     就像"顾客点菜"
└─────────────┬───────────────────────┘
              │
              │ "帮我执行这个操作"
              ▼
┌─────────────────────────────────────┐
│  连接层 (Connection Layer)            │  ← 帮你传话的"服务员"
│  管理连接池、执行SQL、事务管理          │     你不直接碰它
└─────────────┬───────────────────────┘
              │
              │ "我要连数据库"
              ▼
┌─────────────────────────────────────┐
│  实现层 (Implementation)              │  ← 实际干活的"厨房"
│  MySQLConnection / PostgreSQL...     │     不同数据库有不同的"厨师"
└─────────────────────────────────────┘

为什么要分层?

不分层 分层
所有代码写一起,改一处全乱 每层只管自己的事 ✅
换数据库要改所有代码 换数据库只改实现层 ✅
出错了不知道哪儿出问题 分层调试,快速定位 ✅

第2步:从连接数据库开始------基础操作

2.1 三种数据库,三种连接方式

复制代码
┌────────────────────────────────────────────────────────────┐
│                       关系型数据库                           │
│                                                             │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐     │
│  │ MySQL        │  │ PostgreSQL   │  │ SQLite       │     │
│  │ 企业首选      │  │ 复杂查询强    │  │ 小项目测试   │     │
│  │ 生产环境      │  │ JSON支持好    │  │ 无需安装     │     │
│  └──────────────┘  └──────────────┘  └──────────────┘     │
│        ↓                  ↓                  ↓              │
│   端口3306           端口5432          文件或内存            │
│   需要安装           需要安装          无需安装              │
└────────────────────────────────────────────────────────────┘

2.2 MySQL 连接详解

python 复制代码
from Base.Repository.connections.mysqlConnection import MySQLConnection

mysql_db = MySQLConnection(
    host="localhost",        # 数据库服务器的地址
                             # localhost = 本机
                             # 192.168.1.100 = 远程服务器

    user="root",             # 用户名
    password="your_password", # 密码
    database="my_app",       # 数据库名
    port=3306,               # 端口号(MySQL默认3306)
    charset="utf8mb4",       # 字符编码(支持中文)

    # 🔑 连接池参数(重点!)
    mincached=2,        # 池子里最少保持2个空闲连接
    maxcached=10,       # 池子里最多保持10个空闲连接
    maxconnections=20,  # 总共最多创建20个连接
    blocking=False,     # 连接池满了直接报错,不等待
)

2.3 什么是连接池------核心概念

连接池 = 数据库连接的"停车场"。

没有连接池时:
复制代码
程序要查数据库:
  Step 1: 建立连接(3秒)        ← 慢!
  Step 2: 发送 SQL 查询(0.1秒)
  Step 3: 断开连接(1秒)        ← 浪费时间!
  总耗时:4.1秒

如果查100次:4.1秒 × 100 = 410秒 = 6.8分钟!💥
有连接池时:
复制代码
程序启动时:
  建好 2 个连接,放在"停车场"(池子)里待命

程序要查数据库:
  Step 1: 从停车场拿一个连接(0.01秒)← 快!
  Step 2: 发送 SQL 查询(0.1秒)
  Step 3: 用完还回停车场(0.01秒)    ← 不用断开!
  总耗时:0.12秒

如果查100次:0.12秒 × 100 = 12秒!✅

类比:

场景 没有连接池 有连接池
打电话 每次都要拨号、等接通 专线直连,拿起来就说
银行 每次去都要排队取号 VIP专属窗口,随到随办
停车 每次都要找车位、停好 有专属车位,来了就停

连接池参数详解:

python 复制代码
mincached=2         # 最少保留 2 个空闲连接
                    # 像银行"至少开2个窗口"

maxcached=10        # 最多保留 10 个空闲连接
                    # 像银行"最多开10个窗口"

maxconnections=20   # 总共最多 20 个连接(含正在用的+空闲的)
                    # 像银行"整个大厅最多容纳20人"

blocking=False      # False = 窗口满了直接拒绝
                    # True = 窗口满了排队等

2.4 PostgreSQL 和 SQLite 的区别

python 复制代码
# PostgreSQL(比 MySQL 更强大,适合复杂查询)
from Base.Repository.connections.postgresConnection import PostgreSQLConnection

pg_db = PostgreSQLConnection(
    host="localhost",
    user="postgres",
    password="your_password",
    database="my_app",
    port=5432,           # PostgreSQL 默认端口
)

# SQLite(最简单,无需安装,适合测试)
from Base.Repository.connections.sqliteConnection import SQLiteConnection

# 方式1:存文件(持久保存)
file_db = SQLiteConnection(database="my_app.db")

# 方式2:内存数据库(程序结束就没了,适合测试)
mem_db = SQLiteConnection(database=":memory:")

三种数据库对比:

数据库 适用场景 安装难度 性能 功能
MySQL 企业生产环境 中等 高 全面
PostgreSQL 复杂查询、JSON数据 中等 高 最强
SQLite 测试、小项目、手机App 无需安装 中 简单

第3步:用 BaseDBModel 操作数据库------最常用部分

3.1 BaseDBModel 是什么

BaseDBModel = 数据库表的"Python 替身"。

复制代码
数据库里的 users 表:
┌────┬──────┬───────┬──────┐
│ id │ name │ email │ age  │
├────┼──────┼───────┼──────┤
│ 1  │ 张三  │ zs@.. │ 25   │
│ 2  │ 李四  │ ls@.. │ 30   │
└────┴──────┴───────┴──────┘

Python 里的 User 类:
class User(BaseDBModel):
    id: int
    name: str
    email: str
    age: int

一个 User 对象 = 表里的一行数据 ✅

3.2 定义一个模型(定义表结构)

python 复制代码
from Base.Repository.base.baseDBModel import BaseDBModel
from typing import Optional, ClassVar

class User(BaseDBModel):
    """用户表模型"""

    # ━━━━ 第1部分:表名和建表SQL(可选)━━━━
    table_alias: ClassVar[str] = "users"   # 指定表名

    create_table_sql: ClassVar[str] = """  # 建表SQL
    CREATE TABLE `users` (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(100) NOT NULL,
        email VARCHAR(255) NOT NULL,
        age INT,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
    """

    # ━━━━ 第2部分:字段定义(必填)━━━━
    id: Optional[int] = None   # 主键,None表示"新记录,还没存入数据库"
    name: str                  # 必填字段(不能为空)
    email: str                 # 必填字段
    age: Optional[int] = None  # 可选字段(可以为空)

    # ━━━━ 第3部分:自定义方法(按需添加)━━━━
    @classmethod
    def get_by_email(cls, email: str):
        """按邮箱查找用户"""
        results = cls.find_by(email=email, limit=1)
        return results[0] if results else None

字段类型说明:

python 复制代码
# 不同的 Python 类型对应不同的数据库类型
id: int                    → INT(整数)
name: str                  → VARCHAR(字符串)
age: Optional[int]         → INT(可为空)
price: float               → DECIMAL/DOUBLE(小数)
is_active: bool            → TINYINT(1)(布尔值)
created_at: datetime       → TIMESTAMP(时间戳)
description: Optional[str] → TEXT(长文本,可为空)

3.3 CRUD 操作详解------增删改查

📌 创建(Create)------ 插入新数据
python 复制代码
# 方式1:创建对象后 save()
user = User(name="张三", email="zs@example.com", age=25)
new_id = user.save()        # 返回新插入的 ID,比如 new_id = 5

# 方式2:批量插入(比循环 save() 快10倍以上!)
users = [
    User(name="张三", email="zs@example.com"),
    User(name="李四", email="ls@example.com"),
    User(name="王五", email="ww@example.com"),
]
ids = User.bulk_insert(users, batch_size=500)
# 返回 [5, 6, 7] 三个新ID
# batch_size=500 表示每500条一批(避免SQL太长)

save() 的智能判断:

python 复制代码
# 情况1:id 是 None(新记录)→ 执行 INSERT
user = User(name="新用户")   # id 自动为 None
user.save()                  # → INSERT INTO users (name) VALUES ('新用户')

# 情况2:id 有值(已有记录)→ 执行 UPDATE
user = User(id=5, name="改过的用户")
user.save()                  # → UPDATE users SET name='改过的用户' WHERE id=5
📌 读取(Read)------ 查询数据
python 复制代码
# ━━━━ 按 ID 查一条 ━━━━
user = User.get_by_id(1)     # 返回 User 对象,或 None
print(user.name)             # "张三"

# ━━━━ 查所有 ━━━━
users = User.get_all()       # 返回 [User, User, User, ...]
for user in users:
    print(user.name)

# ━━━━ 分页查询 ━━━━
users = User.get_all(limit=10, offset=0)   # 第1页,每页10条
users = User.get_all(limit=10, offset=10)  # 第2页(跳过前10条)
users = User.get_all(limit=10, offset=20)  # 第3页(跳过前20条)

# ━━━━ 按条件查询 ━━━━
users = User.find_by(age=25)              # 查年龄=25的所有用户
users = User.find_by(age=25, name="张三")  # 多条件(AND逻辑)
                                         # WHERE age=25 AND name='张三'

# ━━━━ 只取第一条 ━━━━
user = User.find_one_by(email="zs@example.com")

# ━━━━ 统计数量 ━━━━
total = User.count()                     # 总记录数
count = User.count(age=25)               # 年龄=25的有多少条
📌 更新(Update)------ 修改数据
python 复制代码
# 方式1:查出来 → 改属性 → save()
user = User.get_by_id(1)
user.age = 26              # 改年龄
user.email = "new@example.com"  # 改邮箱
user.save()                # 保存修改

# 方式2:直接 update()
user = User.get_by_id(1)
user.update(age=27)        # 直接传参更新
user.update(age=28, email="another@example.com")  # 同时更新多个字段
📌 删除(Delete)------ 删除数据
python 复制代码
# 方式1:查出来后删除
user = User.get_by_id(1)
user.delete()              # 删除这条记录

# 方式2:按ID直接删除
User.delete_by_id(1)       # 不用先查询

3.4 CRUD 操作速查表

python 复制代码
# ===== 创建 =====
user = User(name="张三")
user.save()                         # 单条插入
User.bulk_insert([user1, user2])   # 批量插入

# ===== 查询 =====
User.get_by_id(1)                   # 按ID查一条
User.get_all()                      # 查所有
User.get_all(limit=10, offset=0)    # 分页
User.find_by(age=25)                # 按条件查
User.find_one_by(email="x@x.com")   # 只取第一条
User.count()                        # 统计总数

# ===== 更新 =====
user.age = 26; user.save()          # 方式1
user.update(age=26)                 # 方式2

# ===== 删除 =====
user.delete()                       # 删除实例
User.delete_by_id(1)                # 按ID删除

3.5 建表操作

python 复制代码
# 检查表是否存在
if not User.table_exists():
    # 用 create_table_sql 中定义的SQL建表
    User.create_table()
    print("表创建成功!")
else:
    print("表已存在,跳过创建")

第4步:连接管理------多数据库场景

4.1 什么时候需要多数据库

场景 说明
读写分离 写操作走主库,读操作走从库
分库分表 订单库、用户库分开存
测试环境 测试库和生产库分开

4.2 连接优先级------重要概念

一个模型到底用哪个数据库连接?优先级如下:

复制代码
优先级最高:实例级连接
    │ user.set_connection(write_db)  ← 这个实例专用
    ↓ 没找到?
优先级中等:类级连接
    │ User.set_db_connection(user_db) ← 这个类专用
    ↓ 没找到?
优先级最低:全局默认连接
    │ BaseDBModel.set_default_db_connection(mysql_db) ← 全局默认

图解:

复制代码
┌─────────────────────────────────────────────┐
│              全局默认连接                      │
│  BaseDBModel.set_default_db_connection(db)  │
│  ↓ 所有模型都默认用这个                        │
└─────────────────────────────────────────────┘
                ▲
                │ 覆盖
┌─────────────────────────────────────────────┐
│              类级连接                         │
│  User.set_db_connection(user_db)            │
│  ↓ User 类用这个,其他类还是用全局默认          │
└─────────────────────────────────────────────┘
                ▲
                │ 覆盖
┌─────────────────────────────────────────────┐
│              实例级连接                       │
│  user.set_connection(write_db)              │
│  ↓ 这个 user 实例用这个                       │
└─────────────────────────────────────────────┘

4.3 读写分离实战

python 复制代码
# Step 1:创建两个连接
read_db = MySQLConnection(host="192.168.1.100", ...)   # 读库(从库)
write_db = MySQLConnection(host="192.168.1.101", ...)  # 写库(主库)

# Step 2:设置全局默认为读库(安全,大部分操作都是读)
BaseDBModel.set_default_db_connection(read_db)

# Step 3:查询自动用读库
users = User.get_all()              # 走读库 ✅
user = User.get_by_id(1)            # 走读库 ✅

# Step 4:写入时临时切换到写库
new_user = User(name="新用户")
new_user.set_connection(write_db)   # 这条走写库 ✅
new_user.save()                      # INSERT → 主库

# 或者改完后切回来
new_user.set_connection(read_db)    # 后续查询又走读库

4.4 ConnectionManager------统一管理多个连接

python 复制代码
from Base.Repository.base.connectionManager import ConnectionManager

# 注册连接(给每个连接起个名字)
ConnectionManager.register("read", read_db, is_default=True)   # 设为默认
ConnectionManager.register("write", write_db)
ConnectionManager.register("order", order_db)   # 订单库
ConnectionManager.register("user", user_db)     # 用户库

# 获取连接
default_db = ConnectionManager.get_default()   # 获取默认连接(read)
write_db = ConnectionManager.get("write")      # 按名字获取
all_names = ConnectionManager.list_keys()       # ['read', 'write', 'order', 'user']

# 程序退出时清理
ConnectionManager.close_all()

4.5 项目预设的模型基类

项目已经帮你创建了两个带连接配置的基类:

python 复制代码
# ━━━━ 使用默认数据库连接 ━━━━
from Base.Repository.models.defaultDbModel import DefaultDbModel

class MyModel(DefaultDbModel):
    id: Optional[int] = None
    name: str
    # 继承后自动绑定默认数据库,不用再设置连接

# ━━━━ 使用 base_module 数据库连接 ━━━━
from Base.Repository.models.moduleDbModel import BaseModuleDBModel

class ConfigModel(BaseModuleDBModel):
    id: Optional[int] = None
    key: str
    value: str
    # 继承后自动绑定 base_module 数据库

区别:连接的目标数据库不同,其他完全一样。


第5步:向量数据库(Milvus)------AI 时代的新物种

5.1 什么是向量数据库

向量数据库 = 专门存"向量"的数据库。

传统数据库 vs 向量数据库
传统数据库 向量数据库
存什么 文本、数字、日期 向量(一串数字)
查什么 "年龄=25" "和这段话最相似"
怎么查 精确匹配 计算向量距离
例子 查"张三的订单" 查"和'人工智能入门'最像的文章"

5.2 向量是什么------核心概念

向量 = 把文字/图片变成一串数字。

复制代码
文字:"特斯拉 Model Y 续航"

↓ AI 模型处理

向量:[0.72, 0.15, 0.88, 0.34, 0.56, ...]  ← 768个数字

文字:"Model Y 能跑多远"

↓ 同一个 AI 模型处理

向量:[0.70, 0.18, 0.85, 0.30, 0.58, ...]  ← 768个数字

对比两串数字:
  0.72 vs 0.70  ← 接近
  0.15 vs 0.18  ← 接近
  0.88 vs 0.85  ← 接近
  ...

结论:这两句话意思相近 ✅

5.3 向量搜索的过程

复制代码
用户提问:"特斯拉电池能用多久?"
            │
            ▼
Step 1: 把问题转成向量
            │ [0.65, 0.22, 0.71, ...]
            ▼
Step 2: 在向量数据库里找"距离最近"的向量
            │
            │ ┌────────────────────────────────┐
            │ │ Milvus 向量数据库                 │
            │ │                                 │
            │ │ [0.72, 0.15, ...] → "特斯拉续航550km"  ← 距离近 ✅
            │ │ [0.68, 0.20, ...] → "Model Y续航强"   ← 距离近 ✅
            │ │ [0.30, 0.85, ...] → "今天天气真好"    ← 距离远 ❌
            │ │                                 │
            │ └────────────────────────────────┘
            ▼
Step 3: 返回最相似的几条记录
            │
            ▼
        ["特斯拉续航550km", "Model Y续航强", ...]

5.4 两种向量:密集向量 vs 稀疏向量

复制代码
┌─────────────────────────────────────────────────────┐
│                    密集向量                          │
│                                                     │
│  每个"维度"都有值:                                   │
│  [0.72, 0.15, 0.88, 0.34, 0.56, 0.12, ...]         │
│                                                     │
│  用途:语义相似度("意思相近")                        │
│  例子:"续航" ≈ "能跑多远" ≈ "电池寿命"               │
│                                                     │
│  生成方式:AI 模型(BERT、GPT Embedding 等)          │
└─────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────┐
│                    稀疏向量                          │
│                                                     │
│  大部分维度是 0,只有少数位置有值:                     │
│  [0, 0, 0.85, 0, 0, 0.72, 0, 0, 0, 0.45, 0, ...]   │
│   ↑         ↑                ↑                     │
│  关键词1   关键词2          关键词3                  │
│                                                     │
│  用途:关键词匹配("包含这个词")                      │
│  例子:"续航" → 只匹配包含"续航"的文档                │
│                                                     │
│  生成方式:BM25 算法(类似搜索引擎的倒排索引)          │
└─────────────────────────────────────────────────────┘

为什么要两种向量?

复制代码
场景:用户问"特斯拉的续航如何?"

纯密集向量搜索:
  → 可能匹配到"Model Y 能跑多远" ✅(语义对)
  → 但也可能匹配到"电动车电池技术发展" ❌(有关联但不准确)

纯稀疏向量搜索:
  → 只匹配包含"特斯拉"和"续航"的文档
  → 如果用户说"Model Y 电池能用多久" → 匹配不到 ❌(词不一样)

混合搜索(两种向量结合):
  → 密集向量找到语义相近的
  → 稀疏向量找到关键词匹配的
  → 综合排序 → 最准确 ✅

5.5 定义向量模型

python 复制代码
from Base.Repository.base.baseVDB import BaseVDBModel
from typing import Optional
from pydantic import Field

class Document(BaseVDBModel):
    """文档向量模型"""

    # ━━━━ 主键字段 ━━━━
    id: Optional[int] = Field(
        default=0,
        json_schema_extra={
            'is_primary': True,   # 这是主键
            'auto_id': True       # 自动生成ID
        }
    )

    # ━━━━ 普通文本字段 ━━━━
    title: str = Field(
        default="",
        json_schema_extra={'max_length': 256}  # 最大长度256
    )

    # ━━━━ BM25 文本字段(会被分词,用于关键词搜索)━━━━
    content: str = Field(
        default="",
        json_schema_extra={
            'enable_match': True,      # 启用匹配
            'enable_analyzer': True,   # 启用分词
            'max_length': 65535        # 最大长度
        }
    )

    # ━━━━ 密集向量字段 ━━━━
    embedding: list[float] = Field(
        default=[],
        json_schema_extra={'dim': 768}  # 768维(必须和你的embedding模型一致)
    )

    # ━━━━ 稀疏向量字段(自动从 content 生成)━━━━
    content_sparse: list[float] = Field(
        default=[],
        json_schema_extra={
            'is_sparse_vector': True,       # 这是稀疏向量
            'bm25_source_field': 'content'  # 从 content 字段生成
        }
    )

    # ━━━━ 集合配置 ━━━━
    collection_alias = "my_documents"  # Milvus 集合名
    description = "文档向量集合"

5.6 向量数据库操作详解

📌 插入数据
python 复制代码
# 方式1:单条插入
doc = Document(
    title="AI入门教程",
    content="人工智能是研究如何使计算机模拟人类智能的学科...",
    embedding=[0.1, 0.2, 0.3, ...]  # 768维向量
)
doc.save()  # 自动生成 ID

# 方式2:批量插入
docs = [
    Document(title="文档1", content="...", embedding=[...]),
    Document(title="文档2", content="...", embedding=[...]),
]
Document.batch_insert(docs)
📌 纯向量搜索
python 复制代码
# 找和某个向量最相似的 10 条记录
results = Document.search(
    data=[0.1, 0.2, 0.3, ...],   # 查询向量(768维)
    limit=10                      # 返回10条
)

for r in results:
    print(f"标题:{r.title}")
    print(f"内容:{r.content}")
    print(f"相似度:{r.distance}")  # 距离越小越相似
    print("---")
📌 混合搜索(推荐)------语义 + 关键词
python 复制代码
results = Document.hybrid_search(
    queries=[
        {
            'data': [0.1, 0.2, ...],    # 密集向量
            'field': 'embedding',        # 搜索这个字段
            'type': 'dense',             # 类型:密集向量
        },
        {
            'data': "人工智能",           # 关键词文本
            'field': 'content_sparse',   # 搜索这个字段
            'type': 'sparse',            # 类型:稀疏向量
        }
    ],
    limit=10,                # 返回10条
    weights=[0.7, 0.3]       # 密集向量权重0.7,稀疏向量权重0.3
)

# 权重解释:
# weights=[0.7, 0.3] → 密集向量更重要,侧重"语义相似"
# weights=[0.3, 0.7] → 稀疏向量更重要,侧重"关键词匹配"
# weights=[0.5, 0.5] → 两者均衡
📌 标量查询(按条件过滤)
python 复制代码
# 类似 SQL 的 WHERE 条件
results = Document.query(
    filter='title like "AI%"',  # 标题以"AI"开头
    limit=10
)

results = Document.find_by(filter='title like "AI%"')

count = Document.count(filter='title like "AI%"')
📌 删除和更新
python 复制代码
# 删除
Document.delete(filter='title == "过期文档"')

# 更新(存在则更新,不存在则插入)
doc = Document(id=1, title="新标题", ...)
Document.upsert([doc])

5.7 BaseVDBModel 的自动化能力

python 复制代码
# 你不需要手动创建集合,第一次使用时自动创建

# 你不需要手动定义 Schema,框架根据 Field 自动推断

# 你不需要手动建索引,默认自动创建:
#   - 密集向量:HNSW 索引(COSINE 距离)
#   - 稀疏向量:BM25 索引

# 你只需要定义好模型,然后直接用!

第6步:完整数据流示例

6.1 关系型数据库完整流程

python 复制代码
# Step 1:创建连接
from Base.Repository.connections.mysqlConnection import MySQLConnection

db = MySQLConnection(
    host="localhost",
    user="root",
    password="password",
    database="my_app"
)

# Step 2:定义模型
from Base.Repository.base.baseDBModel import BaseDBModel

class User(BaseDBModel):
    table_alias = "users"
    create_table_sql = """
    CREATE TABLE users (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(100),
        email VARCHAR(255),
        age INT
    )
    """
    id: Optional[int] = None
    name: str
    email: str
    age: Optional[int] = None

# Step 3:设置连接
User.set_db_connection(db)

# Step 4:建表(如果不存在)
if not User.table_exists():
    User.create_table()

# Step 5:CRUD 操作
# 创建
user = User(name="张三", email="zs@example.com", age=25)
user.save()
print(f"新用户ID:{user.id}")

# 查询
found = User.get_by_id(user.id)
print(f"查到用户:{found.name}")

# 更新
found.age = 26
found.save()

# 删除
found.delete()

6.2 向量数据库完整流程

python 复制代码
# Step 1:创建连接
from Base.Repository.connections.milvusConnection import MilvusVDBConnection

vdb = MilvusVDBConnection(
    host="localhost",
    port="19530"
)

# Step 2:定义向量模型
from Base.Repository.base.baseVDB import BaseVDBModel

class Article(BaseVDBModel):
    collection_alias = "articles"

    id: Optional[int] = Field(0, json_schema_extra={'is_primary': True, 'auto_id': True})
    title: str = Field("", json_schema_extra={'max_length': 256})
    content: str = Field("", json_schema_extra={'enable_match': True, 'enable_analyzer': True})
    embedding: list[float] = Field([], json_schema_extra={'dim': 768})
    content_sparse: list[float] = Field([], json_schema_extra={'is_sparse_vector': True, 'bm25_source_field': 'content'})

# Step 3:设置连接
Article.set_vdb_connection(vdb)

# Step 4:插入数据(假设已有 embedding 函数)
def get_embedding(text):
    # 调用 AI 模型生成向量
    return [0.1, 0.2, ...]  # 768维

article = Article(
    title="AI入门",
    content="人工智能是研究如何使计算机模拟人类智能...",
    embedding=get_embedding("AI入门 人工智能是研究如何使计算机模拟人类智能...")
)
article.save()

# Step 5:混合搜索
query_text = "什么是AI?"
query_vector = get_embedding(query_text)

results = Article.hybrid_search(
    queries=[
        {'data': query_vector, 'field': 'embedding', 'type': 'dense'},
        {'data': query_text, 'field': 'content_sparse', 'type': 'sparse'}
    ],
    limit=5,
    weights=[0.7, 0.3]
)

for r in results:
    print(f"标题:{r.title}")
    print(f"相似度:{r.distance}")

第7步:FAQ 深度解答

Q1:连接失败会怎样?程序会崩溃吗?

答:不会崩溃,优雅降级。

python 复制代码
# 连接失败时,内部 _is_available = False
db = MySQLConnection(host="不存在的地址", ...)

# 后续所有操作静默跳过,返回安全的默认值
User.get_all()        # 返回 []
User.save()           # 返回 -1
User.count()          # 返回 0

# 程序继续运行,只是数据库功能暂时不可用

类比:就像银行系统------某个窗口关闭了,其他窗口还能办业务,只是这一个功能暂时不可用。

Q2:我该继承 DefaultDbModel 还是 BaseDBModel?

复制代码
┌─────────────────────────────────────────┐
│  DefaultDbModel                          │
│  已绑定默认数据库                         │
│  适合:大多数场景                          │
│  用法:直接继承,不用设置连接              │
└─────────────────────────────────────────┘

┌─────────────────────────────────────────┐
│  BaseDBModel                             │
│  需要手动设置连接                         │
│  适合:多数据库、读写分离                  │
│  用法:继承后调用 set_db_connection()     │
└─────────────────────────────────────────┘

建议:优先用 DefaultDbModel,简单省事 ✅

Q3:SQLite 和 MySQL 使用上有什么区别?

答:对模型层来说,几乎没区别。

python 复制代码
# MySQL
mysql_db = MySQLConnection(host="localhost", ...)
User.set_db_connection(mysql_db)
user = User.get_by_id(1)  # 正常工作

# SQLite
sqlite_db = SQLiteConnection(database="app.db")
User.set_db_connection(sqlite_db)
user = User.get_by_id(1)  # 同样正常工作!

# 底层差异(占位符)已被框架处理:
# MySQL:  SELECT * FROM users WHERE id = %s
# SQLite: SELECT * FROM users WHERE id = ?
# 你不需要关心!

Q4:批量插入 bulk_insert 为什么快?

python 复制代码
# ❌ 循环 save():每条一个 SQL
for user in users:
    user.save()
# 执行 100 次 SQL:
# INSERT INTO users (name) VALUES ('张三')
# INSERT INTO users (name) VALUES ('李四')
# ...(100次)

# ✅ bulk_insert():一条 SQL 插多行
User.bulk_insert(users, batch_size=100)
# 执行 1 次 SQL:
# INSERT INTO users (name) VALUES ('张三'),('李四'),(...),...(100条)

# 性能对比:
# 循环 save():   100条 × 10ms = 1000ms = 1秒
# bulk_insert():  1条 × 50ms = 50ms
# 快 20 倍!

Q5:什么时候需要向量数据库?

复制代码
┌─────────────────────────────────────────┐
│         ✅ 适合向量数据库的场景            │
├─────────────────────────────────────────┤
│ 语义搜索:"找和这段话意思相近的文章"        │
│ 图片搜索:"找和这张图最像的图"             │
│ 推荐系统:"找和这个用户兴趣相似的其他用户"   │
│ 问答系统:"找和历史问题相似的问题"         │
└─────────────────────────────────────────┘

┌─────────────────────────────────────────┐
│         ❌ 不需要向量数据库的场景          │
├─────────────────────────────────────────┤
│ 精确查询:"查ID=1001的订单"               │
│ 范围查询:"查2026年7月的所有订单"          │
│ 统计聚合:"统计每个用户的订单数量"         │
│ 事务操作:"转账、退款"                    │
└─────────────────────────────────────────┘

结论:
  精确/范围/统计 → MySQL ✅
  语义相似搜索 → Milvus ✅
  两者结合 → 最强 ✅

Q6:向量维度(dim=768)怎么确定?

答:由你用的 Embedding 模型决定。

复制代码
不同的 AI 模型输出不同维度:

OpenAI text-embedding-3-small:   1536 维
OpenAI text-embedding-3-large:   3072 维
阿里云 text-embedding-v3:         1024 维
BERT-base:                        768 维
MiniLM:                           384 维

你必须保持一致:
  模型输出 768 维 → dim=768 ✅
  模型输出 1536 维 → dim=1536 ✅
  模型输出 768 维 → dim=1024 ❌ 报错!

一句话总结

复制代码
┌─────────────────────────────────────────────────────┐
│                                                     │
│  Repository 包 = 数据库操作的"翻译官"                │
│                                                     │
│  你用 Python 对象:                                  │
│    user.save()                                      │
│    User.get_by_id(1)                                │
│    doc.search(vector)                               │
│                                                     │
│  它帮你翻译成:                                       │
│    INSERT INTO users ...                            │
│    SELECT * FROM users WHERE id=1                   │
│    向量相似度搜索                                    │
│                                                     │
│  你不用写 SQL,不用关心底层细节                       │
│                                                     │
│  三层架构:                                          │
│    模型层(你用的)                                   │
│      → 连接层(帮你传话的)                           │
│        → 实现层(干活的)                             │
│                                                     │
└─────────────────────────────────────────────────────┘
相关推荐
sell-cloud2 小时前
Prompt Engineering要凉了?Fable 5.5能“猜“意图,但银行正在封杀AI Agent——企业AI的真正护城河是什么
人工智能·prompt
Navicat中国4 小时前
Navicat 18 内置 AI 助手让数据库开发从繁琐操作迈向智能协作
大数据·人工智能·数据库开发
4SAPI4 小时前
多模型请求路由怎么设计?成本、速度和能力如何平衡
人工智能·python·gateway·php
魔乐社区4 小时前
翼芯・智算测试与适配优化专区,让国产算力“选得准、跑得通、用得好“
人工智能·开源·大模型
XCDoris6 小时前
郴州logo设计机构
大数据·人工智能·python
Goboy6 小时前
一个人带三个Agent,我用全新TRAE从0到1搭了个资讯周刊站
人工智能·trae
俊哥V6 小时前
每日 AI 研究简报 · 2026-10-19
人工智能·ai
AI_AGENT_DEV_AI6 小时前
AI英语教培智能体的开发
人工智能
物联网软硬件开发-轨物科技7 小时前
【技术白皮书】光伏清检一体化机器人系统解决方案技术白皮书
大数据·运维·网络·人工智能·机器人
海宇数据7 小时前
零信任架构实战:基于海宇网上踪迹欺诈行为识别构建自动化信贷资信评估网关
运维·人工智能·架构·自动化