perf: 优化文档列表与分块索引查询
- 列表页仅查询展示字段并复用文档分块统计 - 移除文档分页对分块表的关联聚合 - 增加文档分块 document_id 索引和 SQL 回归测试
This commit is contained in:
@@ -5,6 +5,7 @@ import com.easyagents.core.store.StoreResult;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
import tech.easyflow.ai.config.SearcherFactory;
|
||||
import tech.easyflow.ai.entity.Document;
|
||||
@@ -21,6 +22,8 @@ import tech.easyflow.common.web.exceptions.BusinessException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* {@link DocumentServiceImpl} 文档维护回归测试。
|
||||
@@ -30,6 +33,70 @@ import java.util.List;
|
||||
*/
|
||||
public class DocumentServiceImplTest {
|
||||
|
||||
/**
|
||||
* 验证管理端列表只查询展示字段,并直接使用文档表中的分块统计。
|
||||
*
|
||||
* @throws Exception 反射注入异常
|
||||
*/
|
||||
@Test
|
||||
public void getDocumentListShouldAvoidChunkJoinAndLargeFields() throws Exception {
|
||||
DocumentMapper documentMapper = Mockito.mock(DocumentMapper.class);
|
||||
DocumentServiceImpl service = new DocumentServiceImpl();
|
||||
setField(service, "documentMapper", documentMapper);
|
||||
|
||||
service.getDocumentList("1001", 10, 1, null);
|
||||
|
||||
ArgumentCaptor<QueryWrapper> queryCaptor =
|
||||
ArgumentCaptor.forClass(QueryWrapper.class);
|
||||
Mockito.verify(documentMapper).paginateAs(
|
||||
Mockito.eq(1),
|
||||
Mockito.eq(10),
|
||||
queryCaptor.capture(),
|
||||
Mockito.eq(Document.class)
|
||||
);
|
||||
String sql = normalizeSql(queryCaptor.getValue().toSQL());
|
||||
Assert.assertFalse(sql.contains("tb_document_chunk"));
|
||||
Assert.assertFalse(containsSqlIdentifier(sql, "content"));
|
||||
Assert.assertFalse(containsSqlIdentifier(sql, "options"));
|
||||
Assert.assertFalse(sql.contains("group by"));
|
||||
Assert.assertTrue(containsSqlIdentifier(sql, "total_chunks"));
|
||||
Assert.assertTrue(containsSqlIdentifier(sql, "chunk_count"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证公开文档分页继续返回历史详情字段,同时不再关联分块表聚合。
|
||||
*
|
||||
* @throws Exception 反射注入异常
|
||||
*/
|
||||
@Test
|
||||
public void getDocumentListByIdShouldKeepDetailFieldsWithoutChunkJoin()
|
||||
throws Exception {
|
||||
DocumentMapper documentMapper = Mockito.mock(DocumentMapper.class);
|
||||
DocumentServiceImpl service = new DocumentServiceImpl();
|
||||
setField(service, "documentMapper", documentMapper);
|
||||
|
||||
service.getDocumentListById(
|
||||
"1001",
|
||||
10,
|
||||
1,
|
||||
BigInteger.valueOf(2002)
|
||||
);
|
||||
|
||||
ArgumentCaptor<QueryWrapper> queryCaptor =
|
||||
ArgumentCaptor.forClass(QueryWrapper.class);
|
||||
Mockito.verify(documentMapper).paginateAs(
|
||||
Mockito.eq(1),
|
||||
Mockito.eq(10),
|
||||
queryCaptor.capture(),
|
||||
Mockito.eq(Document.class)
|
||||
);
|
||||
String sql = normalizeSql(queryCaptor.getValue().toSQL());
|
||||
Assert.assertFalse(sql.contains("tb_document_chunk"));
|
||||
Assert.assertFalse(sql.contains("group by"));
|
||||
Assert.assertTrue(sql.contains("*"));
|
||||
Assert.assertTrue(containsSqlIdentifier(sql, "chunk_count"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证删除链路在外部索引和分块清理后删除文档主记录。
|
||||
*
|
||||
@@ -252,4 +319,27 @@ public class DocumentServiceImplTest {
|
||||
field.setAccessible(true);
|
||||
field.set(target, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一 SQL 文本格式,便于断言查询结构。
|
||||
*
|
||||
* @param sql 原始 SQL
|
||||
* @return 去除标识符引号并转为小写的 SQL
|
||||
*/
|
||||
private static String normalizeSql(String sql) {
|
||||
return sql.replace("`", "").toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断 SQL 是否包含完整列标识符,避免与同前缀列名混淆。
|
||||
*
|
||||
* @param sql 已标准化的 SQL
|
||||
* @param identifier 列标识符
|
||||
* @return 包含完整标识符时返回 true
|
||||
*/
|
||||
private static boolean containsSqlIdentifier(String sql, String identifier) {
|
||||
return Pattern.compile("\\b" + Pattern.quote(identifier) + "\\b")
|
||||
.matcher(sql)
|
||||
.find();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user