chore: initialize qiming workspace repository
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>app-platform-memory</artifactId>
|
||||
<groupId>com.xspaceagi</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.xspaceagi</groupId>
|
||||
<artifactId>app-platform-memory-infra</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xspaceagi</groupId>
|
||||
<artifactId>app-platform-memory-domain</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.xspaceagi</groupId>
|
||||
<artifactId>system-sdk</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.xspaceagi.memory.infra.dao.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 记忆单元实体
|
||||
* @TableName memory_unit
|
||||
*/
|
||||
@TableName(value = "memory_unit")
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MemoryUnit {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@TableField(value = "_tenant_id")
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 代理ID
|
||||
*/
|
||||
private Long agentId;
|
||||
|
||||
/**
|
||||
* 一级分类
|
||||
*/
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 二级分类
|
||||
*/
|
||||
private String subCategory;
|
||||
|
||||
/**
|
||||
* 内容JSON
|
||||
*/
|
||||
private String contentJson;
|
||||
|
||||
/**
|
||||
* 是否敏感信息(0:否 1:是)
|
||||
*/
|
||||
private Boolean isSensitive;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date created;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private Date modified;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.xspaceagi.memory.infra.dao.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 记忆单元标签实体
|
||||
* @TableName memory_unit_tag
|
||||
*/
|
||||
@TableName(value = "memory_unit_tag")
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MemoryUnitTag {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@TableField(value = "_tenant_id")
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 记忆ID
|
||||
*/
|
||||
private Long memoryId;
|
||||
|
||||
/**
|
||||
* 标签名称
|
||||
*/
|
||||
private String tagName;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date created;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private Date modified;
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.xspaceagi.memory.infra.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.xspaceagi.memory.infra.dao.entity.MemoryUnit;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 记忆单元Mapper
|
||||
*
|
||||
* @description 针对表【memory_unit(记忆单元表)】的数据库操作Mapper
|
||||
* @createDate 2026-03-06
|
||||
* @Entity com.xspaceagi.memory.infra.dao.entity.MemoryUnit
|
||||
*/
|
||||
public interface MemoryUnitMapper extends BaseMapper<MemoryUnit> {
|
||||
|
||||
/**
|
||||
* 总条数查询
|
||||
*
|
||||
* @param queryMap 筛选条件
|
||||
* @return 总条数
|
||||
*/
|
||||
Long queryTotal(@Param("queryMap") Map<String, Object> queryMap);
|
||||
|
||||
/**
|
||||
* 列表查询
|
||||
*
|
||||
* @param queryMap 筛选条件
|
||||
* @param orderColumns 排序
|
||||
* @param startIndex 索引开始位置
|
||||
* @param pageSize 业务大小
|
||||
* @return 列表
|
||||
*/
|
||||
List<MemoryUnit> queryList(@Param("queryMap") Map<String, Object> queryMap,
|
||||
@Param("orderColumns") List<OrderItem> orderColumns,
|
||||
@Param("startIndex") Long startIndex, @Param("pageSize") Long pageSize);
|
||||
|
||||
/**
|
||||
* 根据用户ID和分类查询记忆单元
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param category 一级分类
|
||||
* @return 记忆单元列表
|
||||
*/
|
||||
List<MemoryUnit> findByUserIdAndCategory(@Param("userId") Long userId, @Param("agentId") Long agentId, @Param("category") String category, @Param("subCategory") String subCategory);
|
||||
|
||||
/**
|
||||
* 根据代理ID查询记忆单元
|
||||
*
|
||||
* @param agentId 代理ID
|
||||
* @return 记忆单元列表
|
||||
*/
|
||||
List<MemoryUnit> findByAgentId(@Param("agentId") Long agentId);
|
||||
|
||||
/**
|
||||
* 根据分类和JSON字段值查询记忆单元(精确匹配)
|
||||
*
|
||||
* @param tenantId 租户ID
|
||||
* @param userId 用户ID
|
||||
* @param category 一级分类
|
||||
* @param subCategory 二级分类
|
||||
* @param jsonKey JSON中的键
|
||||
* @param jsonValue JSON中的值
|
||||
* @return 记忆单元列表
|
||||
*/
|
||||
List<MemoryUnit> findByCategoryAndJsonKeyValue(
|
||||
@Param("tenantId") Long tenantId,
|
||||
@Param("userId") Long userId,
|
||||
@Param("category") String category,
|
||||
@Param("subCategory") String subCategory,
|
||||
@Param("jsonKey") String jsonKey,
|
||||
@Param("jsonValue") String jsonValue
|
||||
);
|
||||
|
||||
/**
|
||||
* 根据分类和JSON字段值查询记忆单元(模糊匹配)
|
||||
*
|
||||
* @param tenantId 租户ID
|
||||
* @param userId 用户ID
|
||||
* @param category 一级分类
|
||||
* @param subCategory 二级分类
|
||||
* @param jsonKey JSON中的键
|
||||
* @param jsonValue JSON中的值
|
||||
* @return 记忆单元列表
|
||||
*/
|
||||
List<MemoryUnit> findByCategoryAndJsonKeyValueLike(
|
||||
@Param("tenantId") Long tenantId,
|
||||
@Param("userId") Long userId,
|
||||
@Param("category") String category,
|
||||
@Param("subCategory") String subCategory,
|
||||
@Param("jsonKey") String jsonKey,
|
||||
@Param("jsonValue") String jsonValue
|
||||
);
|
||||
|
||||
/**
|
||||
* 根据分类和JSON多个字段值查询记忆单元
|
||||
*
|
||||
* @param tenantId 租户ID
|
||||
* @param userId 用户ID
|
||||
* @param category 一级分类
|
||||
* @param subCategory 二级分类
|
||||
* @param jsonKeyValues JSON键值对 Map<key, value>
|
||||
* @return 记忆单元列表
|
||||
*/
|
||||
List<MemoryUnit> findByCategoryAndJsonKeyValues(
|
||||
@Param("tenantId") Long tenantId,
|
||||
@Param("userId") Long userId,
|
||||
@Param("category") String category,
|
||||
@Param("subCategory") String subCategory,
|
||||
@Param("jsonKeyValues") Map<String, String> jsonKeyValues
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* 根据用户ID、代理ID和标签查询记忆单元
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param agentId 代理ID
|
||||
* @param tags 标签列表
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param startIndex 索引开始位置
|
||||
* @param pageSize 业务大小
|
||||
* @return 记忆单元列表
|
||||
*/
|
||||
List<MemoryUnit> selectWithJoinTags(@Param("userId") Long userId,
|
||||
@Param("agentId") Long agentId,
|
||||
@Param("tags") List<String> tags,
|
||||
@Param("startTime") Date startTime,
|
||||
@Param("endTime") Date endTime,
|
||||
@Param("startIndex") Long startIndex,
|
||||
@Param("pageSize") Long pageSize);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.xspaceagi.memory.infra.dao.mapper;
|
||||
|
||||
import com.xspaceagi.memory.infra.dao.entity.MemoryUnitTag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* 记忆单元标签Mapper
|
||||
* @description 针对表【memory_unit_tag(记忆单元标签表)】的数据库操作Mapper
|
||||
* @createDate 2026-03-06
|
||||
* @Entity com.xspaceagi.memory.infra.dao.entity.MemoryUnitTag
|
||||
*/
|
||||
public interface MemoryUnitTagMapper extends BaseMapper<MemoryUnitTag> {
|
||||
|
||||
/**
|
||||
* 根据记忆ID查询标签列表
|
||||
*
|
||||
* @param memoryId 记忆ID
|
||||
* @return 标签列表
|
||||
*/
|
||||
List<MemoryUnitTag> findByMemoryId(@Param("memoryId") Long memoryId);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询标签列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 标签列表
|
||||
*/
|
||||
List<MemoryUnitTag> findByUserId(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 根据标签名称查询标签列表
|
||||
*
|
||||
* @param tagName 标签名称
|
||||
* @return 标签列表
|
||||
*/
|
||||
List<MemoryUnitTag> findByTagName(@Param("tagName") String tagName);
|
||||
|
||||
/**
|
||||
* 根据记忆ID删除标签
|
||||
*
|
||||
* @param memoryId 记忆ID
|
||||
* @return 删除数量
|
||||
*/
|
||||
int deleteByMemoryId(@Param("memoryId") Long memoryId);
|
||||
|
||||
/**
|
||||
* 批量插入标签
|
||||
*
|
||||
* @param tags 标签列表
|
||||
* @return 插入数量
|
||||
*/
|
||||
int batchInsert(@Param("tags") List<MemoryUnitTag> tags);
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.xspaceagi.memory.infra.dao.mapper.MemoryUnitMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="com.xspaceagi.memory.infra.dao.entity.MemoryUnit">
|
||||
<id property="id" column="id"/>
|
||||
<result property="tenantId" column="_tenant_id"/>
|
||||
<result property="userId" column="user_id"/>
|
||||
<result property="agentId" column="agent_id"/>
|
||||
<result property="category" column="category"/>
|
||||
<result property="subCategory" column="sub_category"/>
|
||||
<result property="contentJson" column="content_json"/>
|
||||
<result property="isSensitive" column="is_sensitive"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="created" column="created"/>
|
||||
<result property="modified" column="modified"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 查询条件 -->
|
||||
<sql id="base_where">
|
||||
<if test="queryMap.tenantId != null">
|
||||
and _tenant_id = #{queryMap.tenantId}
|
||||
</if>
|
||||
<if test="queryMap.userId != null">
|
||||
and user_id = #{queryMap.userId}
|
||||
</if>
|
||||
<if test="queryMap.agentId != null">
|
||||
and agent_id = #{queryMap.agentId}
|
||||
</if>
|
||||
<if test="queryMap.category != null and queryMap.category != ''">
|
||||
and category = #{queryMap.category}
|
||||
</if>
|
||||
<if test="queryMap.subCategory != null and queryMap.subCategory != ''">
|
||||
and sub_category = #{queryMap.subCategory}
|
||||
</if>
|
||||
<if test="queryMap.isSensitive != null">
|
||||
and is_sensitive = #{queryMap.isSensitive}
|
||||
</if>
|
||||
<if test="queryMap.status != null and queryMap.status != ''">
|
||||
and status = #{queryMap.status}
|
||||
</if>
|
||||
<if test="queryMap.keyword != null and queryMap.keyword != ''">
|
||||
and (category like concat('%',#{queryMap.keyword},'%')
|
||||
or sub_category like concat('%',#{queryMap.keyword},'%')
|
||||
or content_json like concat('%',#{queryMap.keyword},'%'))
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<!-- 总条数查询 -->
|
||||
<select id="queryTotal" resultType="java.lang.Long">
|
||||
select count(*)
|
||||
from memory_unit
|
||||
<where>
|
||||
<include refid="base_where"></include>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<!-- 列表查询 -->
|
||||
<select id="queryList" resultMap="BaseResultMap">
|
||||
select *
|
||||
from memory_unit
|
||||
<where>
|
||||
<include refid="base_where"></include>
|
||||
</where>
|
||||
<choose>
|
||||
<when test="orderColumns != null and orderColumns.size > 0">
|
||||
<foreach collection="orderColumns" item="entity" index="index" separator="," open="order by " close="">
|
||||
<if test="entity != null">
|
||||
${entity.column}
|
||||
<if test="!entity.asc">
|
||||
desc
|
||||
</if>
|
||||
</if>
|
||||
</foreach>
|
||||
</when>
|
||||
<otherwise>
|
||||
order by created desc
|
||||
</otherwise>
|
||||
</choose>
|
||||
limit #{startIndex}, #{pageSize}
|
||||
</select>
|
||||
|
||||
<!-- 根据用户ID和分类查询 -->
|
||||
<select id="findByUserIdAndCategory" resultMap="BaseResultMap">
|
||||
select *
|
||||
from memory_unit
|
||||
where user_id = #{userId}
|
||||
<if test="agentId != null">
|
||||
and agent_id = #{agentId}
|
||||
</if>
|
||||
and category = #{category}
|
||||
and sub_category = #{subCategory}
|
||||
and status = 'active'
|
||||
order by created desc limit 50
|
||||
</select>
|
||||
|
||||
<!-- 根据代理ID查询 -->
|
||||
<select id="findByAgentId" resultMap="BaseResultMap">
|
||||
select *
|
||||
from memory_unit
|
||||
where agent_id = #{agentId}
|
||||
and status = 'active'
|
||||
order by created desc
|
||||
</select>
|
||||
|
||||
<!-- 根据分类和JSON字段值查询(精确匹配) -->
|
||||
<select id="findByCategoryAndJsonKeyValue" resultMap="BaseResultMap">
|
||||
select *
|
||||
from memory_unit
|
||||
where _tenant_id = #{tenantId}
|
||||
and user_id = #{userId}
|
||||
and category = #{category}
|
||||
<if test="subCategory != null and subCategory != ''">
|
||||
and sub_category = #{subCategory}
|
||||
</if>
|
||||
and JSON_CONTAINS(content_json, JSON_QUOTE(#{jsonValue}), '$.${jsonKey}')
|
||||
and status = 'active'
|
||||
order by created desc
|
||||
</select>
|
||||
|
||||
<!-- 根据分类和JSON字段值查询(模糊匹配) -->
|
||||
<select id="findByCategoryAndJsonKeyValueLike" resultMap="BaseResultMap">
|
||||
select *
|
||||
from memory_unit
|
||||
where _tenant_id = #{tenantId}
|
||||
and user_id = #{userId}
|
||||
and category = #{category}
|
||||
<if test="subCategory != null and subCategory != ''">
|
||||
and sub_category = #{subCategory}
|
||||
</if>
|
||||
and JSON_EXTRACT(content_json, '$.${jsonKey}') LIKE CONCAT('%', #{jsonValue}, '%')
|
||||
and status = 'active'
|
||||
order by created desc
|
||||
</select>
|
||||
|
||||
<!-- 根据分类和JSON多个字段值查询 -->
|
||||
<select id="findByCategoryAndJsonKeyValues" resultMap="BaseResultMap">
|
||||
select *
|
||||
from memory_unit
|
||||
where _tenant_id = #{tenantId}
|
||||
and user_id = #{userId}
|
||||
and category = #{category}
|
||||
<if test="subCategory != null and subCategory != ''">
|
||||
and sub_category = #{subCategory}
|
||||
</if>
|
||||
<if test="jsonKeyValues != null and jsonKeyValues.size > 0">
|
||||
and
|
||||
<trim prefix="" prefixOverrides="and">
|
||||
<foreach collection="jsonKeyValues" item="value" index="key" separator=" and ">
|
||||
JSON_CONTAINS(content_json, JSON_QUOTE(#{value}), '$.keyValues.${key}')
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
and status = 'active'
|
||||
order by created desc
|
||||
</select>
|
||||
|
||||
<!-- 根据用户ID、代理ID和标签查询记忆单元 -->
|
||||
<select id="selectWithJoinTags" resultMap="BaseResultMap">
|
||||
select distinct mu.*
|
||||
from memory_unit mu
|
||||
inner join memory_unit_tag mut on mu.id = mut.memory_id
|
||||
<where>
|
||||
<if test="userId != null">
|
||||
and mu.user_id = #{userId}
|
||||
</if>
|
||||
<if test="agentId != null">
|
||||
and mu.agent_id = #{agentId}
|
||||
</if>
|
||||
<if test="tags != null and tags.size > 0">
|
||||
and mut.tag_name in
|
||||
<foreach collection="tags" item="tag" open="(" separator="," close=")">
|
||||
#{tag}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="startTime != null">
|
||||
and mu.created >= #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
and mu.created <= #{endTime}
|
||||
</if>
|
||||
and mu.status = 'active'
|
||||
</where>
|
||||
order by mu.created desc
|
||||
<if test="startIndex != null and pageSize != null">
|
||||
limit #{startIndex}, #{pageSize}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.xspaceagi.memory.infra.dao.mapper.MemoryUnitTagMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="com.xspaceagi.memory.infra.dao.entity.MemoryUnitTag">
|
||||
<id property="id" column="id"/>
|
||||
<result property="tenantId" column="_tenant_id"/>
|
||||
<result property="userId" column="user_id"/>
|
||||
<result property="memoryId" column="memory_id"/>
|
||||
<result property="tagName" column="tag_name"/>
|
||||
<result property="created" column="created"/>
|
||||
<result property="modified" column="modified"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 根据记忆ID查询标签列表 -->
|
||||
<select id="findByMemoryId" resultMap="BaseResultMap">
|
||||
select *
|
||||
from memory_unit_tag
|
||||
where memory_id = #{memoryId}
|
||||
order by created desc
|
||||
</select>
|
||||
|
||||
<!-- 根据用户ID查询标签列表 -->
|
||||
<select id="findByUserId" resultMap="BaseResultMap">
|
||||
select *
|
||||
from memory_unit_tag
|
||||
where user_id = #{userId}
|
||||
order by created desc
|
||||
</select>
|
||||
|
||||
<!-- 根据标签名称查询标签列表 -->
|
||||
<select id="findByTagName" resultMap="BaseResultMap">
|
||||
select *
|
||||
from memory_unit_tag
|
||||
where tag_name = #{tagName}
|
||||
order by created desc
|
||||
</select>
|
||||
|
||||
<!-- 根据记忆ID删除标签 -->
|
||||
<delete id="deleteByMemoryId">
|
||||
delete from memory_unit_tag
|
||||
where memory_id = #{memoryId}
|
||||
</delete>
|
||||
|
||||
<!-- 批量插入标签 -->
|
||||
<insert id="batchInsert">
|
||||
insert into memory_unit_tag (_tenant_id, user_id, memory_id, tag_name, created)
|
||||
values
|
||||
<foreach collection="tags" item="tag" separator=",">
|
||||
(#{tag.tenantId}, #{tag.userId}, #{tag.memoryId}, #{tag.tagName}, #{tag.created})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,153 @@
|
||||
# 记忆管理模块 - 数据字典
|
||||
|
||||
## 表1: memory_unit (记忆单元表)
|
||||
|
||||
### 表说明
|
||||
用于存储AI Agent的记忆单元数据,支持多种类型的记忆分类和管理。
|
||||
|
||||
### 字段说明
|
||||
|
||||
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|--------|------|------|--------|------|
|
||||
| id | BIGINT(20) | 是 | AUTO_INCREMENT | 主键ID,自增 |
|
||||
| _tenant_id | BIGINT(20) | 是 | - | 租户ID,多租户隔离标识 |
|
||||
| user_id | BIGINT(20) | 是 | - | 用户ID,记忆所属用户 |
|
||||
| agent_id | BIGINT(20) | 否 | NULL | 代理ID,关联的AI代理 |
|
||||
| category | VARCHAR(50) | 是 | - | 一级分类,如:工作、学习、生活等 |
|
||||
| sub_category | VARCHAR(100) | 否 | NULL | 二级分类,更细粒度的分类 |
|
||||
| content_json | JSON | 否 | NULL | 记忆内容,JSON格式存储结构化数据 |
|
||||
| is_sensitive | TINYINT(1) | 是 | 0 | 是否敏感信息:0-否,1-是 |
|
||||
| status | ENUM | 是 | 'active' | 状态:active-活跃,archived-已归档,deleted-已删除 |
|
||||
| created | DATETIME | 是 | CURRENT_TIMESTAMP | 创建时间 |
|
||||
| modified | DATETIME | 是 | CURRENT_TIMESTAMP ON UPDATE | 修改时间 |
|
||||
|
||||
### 索引说明
|
||||
|
||||
| 索引名 | 字段 | 类型 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| PRIMARY | id | PRIMARY | 主键索引 |
|
||||
| idx_tenant_user | _tenant_id, user_id | INDEX | 租户用户联合索引,支持多租户查询 |
|
||||
| idx_agent | agent_id | INDEX | 代理ID索引,支持按代理查询 |
|
||||
| idx_category | category, sub_category | INDEX | 分类联合索引,支持分类查询 |
|
||||
| idx_status | status | INDEX | 状态索引,支持状态筛选 |
|
||||
| idx_created | created | INDEX | 创建时间索引,支持时间范围查询 |
|
||||
|
||||
### 字段约束
|
||||
|
||||
- `status` 字段只能为:'active', 'archived', 'deleted'
|
||||
- `is_sensitive` 只能为 0 或 1
|
||||
- `_tenant_id` 和 `user_id` 必须有值,用于数据隔离
|
||||
|
||||
### 使用场景
|
||||
|
||||
1. **短期记忆**: 临时存储对话上下文
|
||||
2. **长期记忆**: 持久化存储重要信息
|
||||
3. **工作记忆**: 当前任务相关的活跃记忆
|
||||
4. **敏感信息**: 标记需要特殊保护的数据
|
||||
|
||||
---
|
||||
|
||||
## 表2: memory_unit_tag (记忆单元标签表)
|
||||
|
||||
### 表说明
|
||||
用于为记忆单元添加标签,支持灵活的分类和检索。
|
||||
|
||||
### 字段说明
|
||||
|
||||
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|--------|------|------|--------|------|
|
||||
| id | BIGINT(20) | 是 | AUTO_INCREMENT | 主键ID,自增 |
|
||||
| _tenant_id | BIGINT(20) | 是 | - | 租户ID,多租户隔离标识 |
|
||||
| user_id | BIGINT(20) | 是 | - | 用户ID,标签创建者 |
|
||||
| memory_id | BIGINT(20) | 是 | - | 记忆ID,关联到memory_unit表 |
|
||||
| tag_name | VARCHAR(100) | 是 | - | 标签名称 |
|
||||
| created | DATETIME | 是 | CURRENT_TIMESTAMP | 创建时间 |
|
||||
| modified | DATETIME | 是 | CURRENT_TIMESTAMP ON UPDATE | 修改时间 |
|
||||
|
||||
### 索引说明
|
||||
|
||||
| 索引名 | 字段 | 类型 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| PRIMARY | id | PRIMARY | 主键索引 |
|
||||
| idx_tenant_user | _tenant_id, user_id | INDEX | 租户用户联合索引 |
|
||||
| idx_memory | memory_id | INDEX | 记忆ID索引,支持按记忆查询标签 |
|
||||
| idx_tag | tag_name | INDEX | 标签名称索引,支持按标签查询 |
|
||||
|
||||
### 外键约束
|
||||
|
||||
| 约束名 | 字段 | 关联表 | 关联字段 | 级联操作 |
|
||||
|--------|------|--------|----------|----------|
|
||||
| fk_memory_tag | memory_id | memory_unit | id | ON DELETE CASCADE |
|
||||
|
||||
### 级联删除说明
|
||||
当删除 memory_unit 表中的记录时,会自动删除 memory_unit_tag 表中对应的标签记录。
|
||||
|
||||
---
|
||||
|
||||
## 表关系
|
||||
|
||||
```
|
||||
memory_unit (1) ──────< (N) memory_unit_tag
|
||||
一对多关系
|
||||
一个记忆可以有多个标签
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 业务规则
|
||||
|
||||
### 1. 数据隔离
|
||||
- 所有数据按 `_tenant_id` 和 `user_id` 进行隔离
|
||||
- 查询时必须包含租户和用户条件
|
||||
|
||||
### 2. 状态管理
|
||||
- 新创建的记忆默认状态为 'active'
|
||||
- 删除操作采用软删除,将状态设置为 'deleted'
|
||||
- 过期记忆应归档为 'archived'
|
||||
|
||||
### 3. 标签规则
|
||||
- 一个记忆可以有多个标签
|
||||
- 标签名称不区分大小写(建议在应用层处理)
|
||||
- 重复标签由应用层控制
|
||||
|
||||
### 4. 敏感信息处理
|
||||
- 标记为敏感的信息需要特殊处理
|
||||
- 敏感信息不应在日志中显示完整内容
|
||||
|
||||
---
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
### 1. 分区策略
|
||||
对于大数据量场景,建议按时间或租户进行分区:
|
||||
```sql
|
||||
-- 按创建时间分区(可选)
|
||||
ALTER TABLE memory_unit PARTITION BY RANGE (TO_DAYS(created)) (
|
||||
PARTITION p_old VALUES LESS THAN (TO_DAYS('2026-01-01')),
|
||||
PARTITION p_current VALUES LESS THAN (MAXVALUE)
|
||||
);
|
||||
```
|
||||
|
||||
### 2. 查询优化
|
||||
- 使用覆盖索引减少回表
|
||||
- 避免SELECT *,只查询需要的字段
|
||||
- 合理使用LIMIT分页
|
||||
|
||||
### 3. 数据清理
|
||||
- 定期清理已删除超过30天的数据
|
||||
- 清理孤立的标签数据
|
||||
- 定期执行ANALYZE TABLE和OPTIMIZE TABLE
|
||||
|
||||
---
|
||||
|
||||
## 数据迁移注意事项
|
||||
|
||||
1. **字符集**: 使用 utf8mb4 以支持emoji等特殊字符
|
||||
2. **时区**: 确保应用服务器和数据库时区一致
|
||||
3. **JSON字段**: MySQL 5.7+ 支持JSON类型,低版本需要使用TEXT
|
||||
4. **外键**: 如需禁用外键检查(批量导入时):
|
||||
```sql
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
-- 执行导入操作
|
||||
SET FOREIGN_KEY_CHECKS=1;
|
||||
```
|
||||
@@ -0,0 +1,243 @@
|
||||
# 记忆管理模块 - MySQL表创建脚本使用说明
|
||||
|
||||
## 📁 文件说明
|
||||
|
||||
### 1. `memory_schema.sql` - 完整版脚本
|
||||
**包含内容:**
|
||||
- 完整的表创建语句
|
||||
- 示例数据插入
|
||||
- 常用查询示例
|
||||
- 数据清理和维护脚本
|
||||
- 性能优化建议
|
||||
|
||||
**适用场景:** 开发环境搭建、功能测试、学习参考
|
||||
|
||||
### 2. `memory_tables_simple.sql` - 简化版脚本
|
||||
**包含内容:**
|
||||
- 纯净的表创建语句
|
||||
- 必要的索引和约束
|
||||
|
||||
**适用场景:** 生产环境部署、快速部署
|
||||
|
||||
### 3. `verify_tables.sql` - 验证脚本
|
||||
**包含内容:**
|
||||
- 表结构检查
|
||||
- 索引验证
|
||||
- 外键约束检查
|
||||
- 数据完整性检查
|
||||
|
||||
**适用场景:** 部署后验证、故障排查
|
||||
|
||||
### 4. `DATA_DICTIONARY.md` - 数据字典
|
||||
**包含内容:**
|
||||
- 详细的字段说明
|
||||
- 索引说明
|
||||
- 业务规则
|
||||
- 性能优化建议
|
||||
|
||||
**适用场景:** 开发参考、文档维护
|
||||
|
||||
---
|
||||
|
||||
## 🚀 使用步骤
|
||||
|
||||
### 步骤1: 选择合适的脚本
|
||||
```bash
|
||||
# 开发环境(推荐)
|
||||
mysql -u root -p < memory_schema.sql
|
||||
|
||||
# 生产环境
|
||||
mysql -u root -p < memory_tables_simple.sql
|
||||
```
|
||||
|
||||
### 步骤2: 验证表创建
|
||||
```bash
|
||||
mysql -u root -p your_database < verify_tables.sql
|
||||
```
|
||||
|
||||
### 步骤3: 检查结果
|
||||
登录MySQL查看:
|
||||
```sql
|
||||
USE your_database;
|
||||
SHOW TABLES LIKE 'memory_unit%';
|
||||
DESCRIBE memory_unit;
|
||||
DESCRIBE memory_unit_tag;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 表结构概览
|
||||
|
||||
### memory_unit (记忆单元表)
|
||||
存储AI Agent的各种记忆数据,支持分类、标签、状态管理。
|
||||
|
||||
**核心字段:**
|
||||
- `id`: 主键
|
||||
- `_tenant_id`, `user_id`: 多租户隔离
|
||||
- `category`, `sub_category`: 分类体系
|
||||
- `content_json`: JSON格式存储记忆内容
|
||||
- `status`: 状态管理
|
||||
|
||||
### memory_unit_tag (记忆标签表)
|
||||
为记忆单元添加灵活的标签支持。
|
||||
|
||||
**核心字段:**
|
||||
- `id`: 主键
|
||||
- `memory_id`: 关联记忆单元(外键)
|
||||
- `tag_name`: 标签名称
|
||||
|
||||
**关系:** 一个记忆可以有多个标签(一对多)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 高级配置
|
||||
|
||||
### 字符集设置
|
||||
```sql
|
||||
-- 确保使用 utf8mb4 支持emoji
|
||||
ALTER DATABASE your_database CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
||||
```
|
||||
|
||||
### 性能优化
|
||||
```sql
|
||||
-- 分析表优化查询
|
||||
ANALYZE TABLE memory_unit;
|
||||
ANALYZE TABLE memory_unit_tag;
|
||||
|
||||
-- 优化表空间
|
||||
OPTIMIZE TABLE memory_unit;
|
||||
OPTIMIZE TABLE memory_unit_tag;
|
||||
```
|
||||
|
||||
### 备份恢复
|
||||
```bash
|
||||
# 备份
|
||||
mysqldump -u root -p your_database memory_unit memory_unit_tag > backup.sql
|
||||
|
||||
# 恢复
|
||||
mysql -u root -p your_database < backup.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 数据示例
|
||||
|
||||
### 记忆单元示例
|
||||
```json
|
||||
{
|
||||
"title": "AI项目开发",
|
||||
"description": "负责AI代理平台的开发工作",
|
||||
"priority": "高",
|
||||
"tags": ["重要", "正在进行"],
|
||||
"metadata": {
|
||||
"start_date": "2026-01-01",
|
||||
"end_date": "2026-06-30"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 标签示例
|
||||
```
|
||||
重要、正在进行、技术、学习、运动、日常
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 1. 外键约束
|
||||
- `memory_unit_tag.memory_id` 有外键约束指向 `memory_unit.id`
|
||||
- 删除记忆会自动删除相关标签(CASCADE)
|
||||
|
||||
### 2. 级联删除
|
||||
如需临时禁用外键检查(批量操作时):
|
||||
```sql
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
-- 执行批量操作
|
||||
SET FOREIGN_KEY_CHECKS=1;
|
||||
```
|
||||
|
||||
### 3. JSON字段
|
||||
- MySQL 5.7+ 原生支持JSON类型
|
||||
- 提供JSON函数:JSON_EXTRACT、JSON_SEARCH等
|
||||
- 自动验证JSON格式
|
||||
|
||||
### 4. 状态管理
|
||||
- 新建记录默认状态为 'active'
|
||||
- 删除采用软删除(设置status为'deleted')
|
||||
- 定期清理归档数据
|
||||
|
||||
---
|
||||
|
||||
## 🔍 常用查询
|
||||
|
||||
### 查询用户的活跃记忆
|
||||
```sql
|
||||
SELECT * FROM memory_unit
|
||||
WHERE user_id = 1001
|
||||
AND status = 'active'
|
||||
ORDER BY created DESC;
|
||||
```
|
||||
|
||||
### 查询记忆及其标签
|
||||
```sql
|
||||
SELECT m.*, t.tag_name
|
||||
FROM memory_unit m
|
||||
LEFT JOIN memory_unit_tag t ON m.id = t.memory_id
|
||||
WHERE m.user_id = 1001
|
||||
AND m.status = 'active';
|
||||
```
|
||||
|
||||
### 按标签查询记忆
|
||||
```sql
|
||||
SELECT DISTINCT m.*
|
||||
FROM memory_unit m
|
||||
INNER JOIN memory_unit_tag t ON m.id = t.memory_id
|
||||
WHERE t.tag_name = '重要'
|
||||
AND m.status = 'active';
|
||||
```
|
||||
|
||||
### 统计用户记忆数量(按分类)
|
||||
```sql
|
||||
SELECT category, COUNT(*) as count
|
||||
FROM memory_unit
|
||||
WHERE user_id = 1001
|
||||
AND status = 'active'
|
||||
GROUP BY category;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 故障排查
|
||||
|
||||
### 问题1: 外键约束错误
|
||||
```sql
|
||||
-- 检查外键状态
|
||||
SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'memory_unit_tag';
|
||||
```
|
||||
|
||||
### 问题2: 字符编码问题
|
||||
```sql
|
||||
-- 检查字符集设置
|
||||
SHOW VARIABLES LIKE 'character%';
|
||||
SHOW VARIABLES LIKE 'collation%';
|
||||
```
|
||||
|
||||
### 问题3: JSON格式错误
|
||||
```sql
|
||||
-- 验证JSON数据
|
||||
SELECT id, JSON_VALID(content_json) as is_valid
|
||||
FROM memory_unit
|
||||
WHERE content_json IS NOT NULL;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
如有问题,请参考:
|
||||
1. `DATA_DICTIONARY.md` - 详细的数据字典
|
||||
2. `verify_tables.sql` - 表结构验证脚本
|
||||
3. 项目文档:`README.md`
|
||||
Reference in New Issue
Block a user