# Task 5.3 Implementation Summary: 向量搜索 DTO ## 任务概述 实现向量搜索应用层的数据传输对象(DTOs),用于在不同层之间传输数据。 **任务要求:** - 创建 `application/vector_search/dtos.py`,定义 DocumentDTO - 实现 DTO 与领域实体的转换方法 - 满足需求 1.4 和 8.1 ## 实现内容 ### 1. 创建的文件 #### src/application/vector_search/dtos.py 定义了三个主要的 DTO 类: 1. **DocumentDTO** - 文档数据传输对象 - 属性:id, content, metadata, embedding, score, created_at, updated_at - 类方法: - `from_entity()` - 从领域实体创建 DTO - `from_dict()` - 从字典创建 DTO - 实例方法: - `to_entity()` - 转换为领域实体 - `to_dict()` - 转换为字典 2. **SearchResultDTO** - 搜索结果数据传输对象 - 属性:document, score, rank - 类方法: - `from_entity()` - 从领域实体创建 DTO - `from_dict()` - 从字典创建 DTO - 实例方法: - `to_dict()` - 转换为字典 3. **SearchResponseDTO** - 搜索响应数据传输对象 - 属性:results, total, query_text, took_ms - 类方法: - `from_dict()` - 从字典创建 DTO - 实例方法: - `to_dict()` - 转换为字典 #### tests/unit/application/vector_search/test_dtos.py 完整的单元测试套件,包含 24 个测试用例: **TestDocumentDTO 类(13 个测试):** - `test_from_entity_basic` - 测试从领域实体创建 DTO(基本情况) - `test_from_entity_with_embedding` - 测试包含嵌入向量的转换 - `test_from_entity_without_embedding` - 测试不包含嵌入向量的转换 - `test_from_entity_with_score` - 测试包含分数的转换 - `test_to_entity_basic` - 测试将 DTO 转换为领域实体(基本情况) - `test_to_entity_with_embedding` - 测试包含嵌入向量的转换 - `test_to_dict_basic` - 测试将 DTO 转换为字典(基本情况) - `test_to_dict_with_optional_fields` - 测试包含可选字段的转换 - `test_from_dict_basic` - 测试从字典创建 DTO(基本情况) - `test_from_dict_with_optional_fields` - 测试包含可选字段的转换 - `test_roundtrip_entity_to_dto_to_entity` - 测试实体 -> DTO -> 实体的往返转换 - `test_roundtrip_dict_to_dto_to_dict` - 测试字典 -> DTO -> 字典的往返转换 - `test_metadata_is_copied` - 测试元数据被复制而不是引用 **TestSearchResultDTO 类(5 个测试):** - `test_from_entity_basic` - 测试从领域实体创建搜索结果 DTO - `test_from_entity_with_embedding` - 测试包含嵌入向量的转换 - `test_to_dict` - 测试将搜索结果 DTO 转换为字典 - `test_from_dict` - 测试从字典创建搜索结果 DTO - `test_roundtrip_dict_to_dto_to_dict` - 测试往返转换 **TestSearchResponseDTO 类(6 个测试):** - `test_to_dict_basic` - 测试将搜索响应 DTO 转换为字典(基本情况) - `test_to_dict_with_timing` - 测试包含耗时的转换 - `test_from_dict_basic` - 测试从字典创建搜索响应 DTO - `test_from_dict_with_timing` - 测试包含耗时的转换 - `test_roundtrip_dict_to_dto_to_dict` - 测试往返转换 - `test_empty_results` - 测试空结果列表 ### 2. 更新的文件 #### src/application/vector_search/README.md 添加了 DTOs 的完整文档,包括: - 每个 DTO 类的属性说明 - 类方法和实例方法的文档 - 使用示例 - 测试文件列表更新 ## 设计决策 ### 1. DTO 与领域实体的解耦 - DTOs 使用基本类型(str, List[float], Dict)而不是值对象 - 提供双向转换方法:`from_entity()` 和 `to_entity()` - 元数据在转换时进行复制,避免修改原始数据 ### 2. 可选字段处理 - `embedding` 字段可选,通过 `include_embedding` 参数控制 - `score` 字段可选,用于搜索结果场景 - `took_ms` 字段可选,用于性能监控 ### 3. 序列化支持 - 提供 `to_dict()` 和 `from_dict()` 方法支持 JSON 序列化 - 可选字段在序列化时只在存在时包含 ### 4. 时间戳处理 - 使用 ISO 格式字符串表示时间戳 - 通过 `Timestamp.to_iso_string()` 和 `Timestamp.from_iso_string()` 进行转换 ## 测试结果 所有 24 个测试用例全部通过: ``` ========================= test session starts ========================= collected 24 items tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_from_entity_basic PASSED [ 4%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_from_entity_with_embedding PASSED [ 8%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_from_entity_without_embedding PASSED [ 12%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_from_entity_with_score PASSED [ 16%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_to_entity_basic PASSED [ 20%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_to_entity_with_embedding PASSED [ 25%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_to_dict_basic PASSED [ 29%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_to_dict_with_optional_fields PASSED [ 33%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_from_dict_basic PASSED [ 37%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_from_dict_with_optional_fields PASSED [ 41%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_roundtrip_entity_to_dto_to_entity PASSED [ 45%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_roundtrip_dict_to_dto_to_dict PASSED [ 50%] tests/unit/application/vector_search/test_dtos.py::TestDocumentDTO::test_metadata_is_copied PASSED [ 54%] tests/unit/application/vector_search/test_dtos.py::TestSearchResultDTO::test_from_entity_basic PASSED [ 58%] tests/unit/application/vector_search/test_dtos.py::TestSearchResultDTO::test_from_entity_with_embedding PASSED [ 62%] tests/unit/application/vector_search/test_dtos.py::TestSearchResultDTO::test_to_dict PASSED [ 66%] tests/unit/application/vector_search/test_dtos.py::TestSearchResultDTO::test_from_dict PASSED [ 70%] tests/unit/application/vector_search/test_dtos.py::TestSearchResultDTO::test_roundtrip_dict_to_dto_to_dict PASSED [ 75%] tests/unit/application/vector_search/test_dtos.py::TestSearchResponseDTO::test_to_dict_basic PASSED [ 79%] tests/unit/application/vector_search/test_dtos.py::TestSearchResponseDTO::test_to_dict_with_timing PASSED [ 83%] tests/unit/application/vector_search/test_dtos.py::TestSearchResponseDTO::test_from_dict_basic PASSED [ 87%] tests/unit/application/vector_search/test_dtos.py::TestSearchResponseDTO::test_from_dict_with_timing PASSED [ 91%] tests/unit/application/vector_search/test_dtos.py::TestSearchResponseDTO::test_roundtrip_dict_to_dto_to_dict PASSED [ 95%] tests/unit/application/vector_search/test_dtos.py::TestSearchResponseDTO::test_empty_results PASSED [100%] ========================= 24 passed in 0.40s ========================== ``` ## 需求追溯 ### Requirement 1.4: 应用层协调领域对象完成用例 ✅ **已满足** - DTOs 提供了应用层和表现层之间的数据传输机制,支持领域实体的转换。 ### Requirement 8.1: 向量数据库相关代码组织到独立模块 ✅ **已满足** - DTOs 位于 `src/application/vector_search/` 模块中,与向量搜索功能相关的其他组件组织在一起。 ## 关键特性 1. **类型安全**:使用 dataclass 提供类型提示和验证 2. **双向转换**:支持 DTO ↔ 领域实体 ↔ 字典的双向转换 3. **可选字段**:灵活处理可选字段(embedding, score, took_ms) 4. **数据隔离**:元数据在转换时进行复制,避免意外修改 5. **完整测试**:24 个测试用例覆盖所有转换场景和边界情况 6. **文档完善**:详细的 docstring 和 README 文档 ## 使用示例 ### 从领域实体创建 DTO ```python from src.application.vector_search.dtos import DocumentDTO from src.domain.vector_search.entities import Document # 创建领域实体 doc = Document(...) # 转换为 DTO(不包含嵌入向量) dto = DocumentDTO.from_entity(doc) # 转换为 DTO(包含嵌入向量) dto = DocumentDTO.from_entity(doc, include_embedding=True) # 转换为 DTO(包含搜索分数) dto = DocumentDTO.from_entity(doc, score=0.95) ``` ### DTO 转换为领域实体 ```python # 从 DTO 转换为领域实体 doc = dto.to_entity() ``` ### JSON 序列化 ```python # 转换为字典(用于 JSON 序列化) data = dto.to_dict() # 从字典创建 DTO(用于 JSON 反序列化) dto = DocumentDTO.from_dict(data) ``` ### 搜索结果处理 ```python from src.application.vector_search.dtos import SearchResultDTO, SearchResponseDTO # 从领域实体创建搜索结果 DTO result_dto = SearchResultDTO.from_entity(search_result) # 创建搜索响应 response = SearchResponseDTO( results=[result_dto1, result_dto2], total=2, query_text="test query", took_ms=150 ) # 序列化为 JSON json_data = response.to_dict() ``` ## 下一步 Task 5.3 已完成。下一个任务是: **Task 5.4**: 实现向量搜索命令处理器 - 创建 `application/vector_search/handlers.py` - 实现 CreateDocumentHandler, UpdateDocumentHandler, DeleteDocumentHandler - 注入仓储和领域服务依赖 ## 总结 Task 5.3 成功实现了向量搜索应用层的 DTOs,提供了: - 3 个 DTO 类(DocumentDTO, SearchResultDTO, SearchResponseDTO) - 完整的双向转换方法(DTO ↔ 领域实体 ↔ 字典) - 24 个单元测试,全部通过 - 详细的文档和使用示例 实现遵循了分层架构原则,DTOs 作为应用层和表现层之间的桥梁,与领域实体解耦,提供了灵活的数据传输和序列化支持。