Documentation ¶
Index ¶
- Constants
- type CompositeIndex
- type Database
- func (db *Database) Close() error
- func (db *Database) Count() int64
- func (db *Database) CreateCompositeIndex(fields []string)
- func (db *Database) CreateIndex(field string)
- func (db *Database) Delete(id string) error
- func (db *Database) FuzzyQuery(field, pattern string) []map[string]interface{}
- func (db *Database) Get(id string) (map[string]interface{}, bool)
- func (db *Database) GetAll() []map[string]interface{}
- func (db *Database) Insert(docData interface{}) error
- func (db *Database) LogLevelOff()
- func (db *Database) PrintIndexContent(field string)
- func (db *Database) Query(field string, value interface{}) []map[string]interface{}
- func (db *Database) QueryComposite(fields []string, values []interface{}) []map[string]interface{}
- func (db *Database) RangeQuery(field string, min, max interface{}) []map[string]interface{}
- func (db *Database) SetLogLevel(level LogLevel)
- func (db *Database) SetLogOutput(output io.Writer)
- func (db *Database) Update(id string, updates map[string]interface{}) error
- type DefaultLogger
- type Document
- type DocumentData
- type Index
- type LogLevel
- type Logger
- type Trie
- type TrieNode
Constants ¶
const ( // 数据库文件名 DataFileName = "data.db" WALFileName = "wal.log" // 文件权限 DBDirPerm = 0755 DBFilePerm = 0644 // 操作类型 OperationInsert = "INSERT" OperationUpdate = "UPDATE" OperationDelete = "DELETE" // 文件打开模式 FileOpenModeRW = os.O_RDWR | os.O_CREATE FileOpenModeWAL = os.O_RDWR | os.O_CREATE | os.O_TRUNC )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CompositeIndex ¶
type CompositeIndex struct {
// contains filtered or unexported fields
}
CompositeIndex 结构体定义了复合索引
type Database ¶
type Database struct {
// contains filtered or unexported fields
}
Database 结构体定义了数据库的核心结构
func NewDatabase ¶
NewDatabase 创建一个新的数据库实例
func (*Database) CreateCompositeIndex ¶
CreateCompositeIndex 方法用于创建复合索引
介绍: CreateCompositeIndex 是一个高级索引创建方法,用于为多个字段的组合创建索引。复合索引在需要 同时满足多个条件的查询中特别有用,如"查找特定年龄范围内且工资超过某个值的员工"。
复合索引的工作原理是将多个字段的值组合成一个唯一的键。这允许数据库在一次查找中匹配多个条件, 大大提高了复杂查询的效率,尤其是在大型数据集上。
这个方法不仅为新文档创建复合索引,还会遍历所有现有文档并为它们建立索引。这确保了索引的完整性, 但在大型数据集上可能会是一个耗时的操作。
需要注意的是,复合索引的字段顺序很重要。查询时必须使用相同的字段顺序才能利用到这个索引。
参数: - fields: 一个字符串切片,包含要创建复合索引的字段名
注意: 这个方法没有返回值,但会在日志中记录索引创建的结果
func (*Database) CreateIndex ¶
CreateIndex 方法用于创建单字段索引
介绍: CreateIndex 是一个关键的数据库操作,用于为指定的字段创建索引。索引是提高查询性能的重要机制, 特别是在大型数据集上。通过创建索引,数据库可以快速定位满足特定条件的文档,而无需扫描整个集合。
这个方法不仅为新文档创建索引,还会遍历现有的所有文档并为它们建立索引。这确保了索引的完整性, 但也意味着在大型数据集上创建索引可能是一个耗时的操作。
索引的实现使用了 sync.Map 来存储索引数据,这提供了良好的并发性能。此外,还使用了 Trie 数据 结构来支持模糊查询,这对于文本搜索等场景非常有用。
需要注意的是,虽然索引可以显著提升读取性能,但会略微降低写入性能,因为每次插入或更新操作都 需要维护索引。因此,应该只为经常在查询中使用的字段创建索引。
参数: - field: 要创建索引的字段名
注意: 这个方法没有返回值,但会在日志中记录索引创建的结果
func (*Database) Delete ¶
Delete 方法用于从数据库中删除指定ID的文档
介绍: Delete 方法是一个关键的数据操作函数,用于从数据库中移除特定的文档。 这个方法不仅从内存中删除文档,还会更新相关的索引,并记录删除操作到WAL(Write-Ahead Log)中。
实现细节: 1. 使用 sync.Map 的 LoadAndDelete 方法原子性地删除文档。 2. 更新所有相关索引以保持数据一致性。 3. 使用 WAL 记录删除操作,确保数据持久性和可恢复性。 4. 使用原子操作更新文档计数,保证并发安全。
参数: - id: 要删除的文档的唯一标识符
返回值: - error: 如果删除过程中发生错误,返回相应的错误信息;如果删除成功或文档不存在,返回 nil
func (*Database) FuzzyQuery ¶
FuzzyQuery 执行模糊查询 field: 要查询的字段名 pattern: 查询模式,支持 '*' 作为通配符 返回匹配的文档列表
func (*Database) Get ¶
Get 方法用于从数据库中获取指定ID的文档
介绍: Get 方法是一个基本的数据检索函数,用于根据文档ID获取完整的文档内容。 这个方法直接从内存中读取数据,因此速度很快,但同时也确保了并发安全。
实现细节: 1. 使用 sync.Map 的 Load 方法安全地获取文档。 2. 使用读锁确保在读取过程中文档不会被修改。 3. 返回文档的直接引用,而不是副本,以提高性能。但这要求调用者不应修改返回的数据。
参数: - id: 要获取的文档的唯一标识符
返回值: - map[string]interface{}: 如果文档存在,返回文档内容 - bool: 表示文档是否存在
func (*Database) GetAll ¶
GetAll 方法用于获取数据库中的所有文档
介绍: GetAll 是一个全量查询方法,它返回数据库中存储的所有文档。 这个方法对于需要处理或分析整个数据集的场景非常有用,比如数据导出、全局统计或批量操作。
实现细节: 1. 该方法使用 sync.Map 的 Range 方法遍历所有存储的文档。 2. 为了保证并发安全,在访问每个文档时都会使用读锁。 3. 方法会创建每个文档的深拷贝,以防止在返回后对原始数据的意外修改。 4. 使用日志记录操作的开始和结束,包括获取的文档总数,有助于监控和调试。
性能考虑: 对于大型数据库,这个方法可能会消耗大量内存和时间。在处理大量数据时, 应考虑使用分页或流式处理的替代方法。
返回值: - []map[string]interface{}: 包含所有文档的切片,每个文档表示为一个 map
func (*Database) Insert ¶
Insert 方法用于向数据库中插入新文档
介绍: Insert 是 jsonDB 的核心方法之一,用于将新文档添加到数据库中。该方法支持两种输入格式: 1. map[string]interface{} 类型的文档数据 2. JSON 格式的字符串
该方法执行以下主要步骤: - 解析和验证输入数据 - 检查文档的唯一性(基于主键) - 将操作记录到 WAL(Write-Ahead Log) - 将文档存储在内存中 - 更新所有相关索引 - 异步将文档写入持久化存储
Insert 方法在整个过程中都采取了必要的并发控制措施,确保了数据的一致性和完整性。 同时,该方法还实现了详细的日志记录,有助于监控和调试。
参数: - docData: 要插入的文档数据,可以是 map[string]interface{} 或 JSON 字符串
返回值: - error: 如果插入过程中发生错误,将返回相应的错误信息;如果插入成功,则返回 nil
func (*Database) PrintIndexContent ¶
PrintIndexContent 方法用于打印指定字段的索引内容
介绍: PrintIndexContent 是一个调试和诊断工具,用于可视化展示数据库中特定字段的索引结构。 这个方法对于理解索引的内部结构、验证索引的正确性,以及调试查询性能问题非常有用。
该方法会遍历指定字段的整个索引结构,并以层级形式打印出每个索引键及其对应的文档ID。 这样可以清晰地看到索引是如何组织数据的,以及哪些文档与特定的索引值相关联。
注意,这个方法主要用于开发和调试目的。在生产环境中,特别是对于大型索引,应谨慎使用, 因为它可能会产生大量的输出并消耗较多的资源。
参数: - field: 要打印索引内容的字段名
注意: 这个方法没有返回值,所有的输出都通过日志系统记录
func (*Database) Query ¶
Query 方法用于在数据库中查询符合特定条件的文档
介绍: Query 方法是 jsonDB 的核心查询功能,它允许用户根据指定的字段和值在数据库中搜索匹配的文档。 该方法支持两种查询模式: 1. 索引查询: 如果查询的字段已建立索引,则使用索引进行快速查询 2. 全表扫描: 如果查询的字段没有索引,则遍历所有文档进行匹配
该方法在查询过程中考虑了并发安全性,使用了适当的锁机制来保护数据访问。 为了处理可能的类型不匹配问题(例如整数和浮点数的比较),该方法使用 toFloat64 函数将值转换为统一的浮点数类型进行比较。
参数: - field: 要查询的字段名 - value: 要匹配的值
返回值: - []map[string]interface{}: 包含所有匹配文档的切片,每个文档表示为一个 map
func (*Database) QueryComposite ¶
QueryComposite 方法用于根据复合索引查询文档
介绍: QueryComposite 是一个高效的查询方法,专门用于处理多字段组合查询。它利用预先创建的复合索引来 快速定位符合多个条件的文档,而无需遍历整个数据集。这种方法特别适用于需要同时满足多个条件的 查询场景,如"查找年龄在25-30之间且工资超过50000的员工"。
复合索引的工作原理是将多个字段的值组合成一个唯一的键,这样可以在一次查找中匹配多个条件。 这种方法大大提高了查询效率,尤其是在大型数据集上执行复杂查询时。
使用复合索引查询时,字段的顺序很重要,必须与创建索引时的顺序一致。这是因为索引键是按照 字段顺序生成的。
参数: - fields: 一个字符串切片,包含要查询的字段名,顺序必须与创建复合索引时的顺序一致 - values: 一个接口切片,包含与fields对应的查询值,顺序必须与fields一致
返回值: - []map[string]interface{}: 包含所有匹配文档的切片,每个文档表示为一个map
func (*Database) RangeQuery ¶
RangeQuery 执行范围查询,返回字段值在指定范围内的所有文档
介绍: RangeQuery 是一个强大的查询功能,允许用户在指定字段上执行范围搜索。 它支持各种数据类型,包括整数、浮点数和日期时间。 该函数首先检查是否存在相关的索引。如果存在,它会利用索引进行快速查询; 否则,它会执行全表扫描。
实现细节: - 使用了 toComparableValue 函数将输入值转换为可比较的类型 - 利用 compareValues 函数进行值的比较,确保不同类型间的正确比较 - 对于索引查询和全表扫描,使用相同的比较逻辑确保结果一致性 - 使用读写锁保证并发安全 - 通过日志记录查询过程,便于调试和性能分析
参数: - field: 要查询的字段名 - min: 范围的最小值 - max: 范围的最大值
返回值: - []map[string]interface{}: 包含所有匹配文档的切片
func (*Database) SetLogOutput ¶
SetLogOutput 设置日志输出
func (*Database) Update ¶
Update 方法用于更新数据库中指定ID的文档
介绍: Update 方法是一个关键的数据操作函数,用于修改数据库中已存在的文档。 这个方法实现了原子性更新,确保在高并发环境下的数据一致性。 它不仅更新内存中的文档,还会更新相关的索引,并记录更新操作到WAL(Write-Ahead Log)中。
实现细节: 1. 使用乐观锁策略(Compare-and-Swap)来处理并发更新。 2. 创建文档的新版本,而不是直接修改原文档,以支持原子性更新。 3. 更新所有相关索引以保持数据一致性。 4. 使用WAL记录更新操作,确保数据持久性和可恢复性。 5. 异步写入数据文件,提高性能。
参数: - id: 要更新的文档的唯一标识符 - updates: 包含要更新的字段和其新值的映射
返回值: - error: 如果更新过程中发生错误,返回相应的错误信息;如果更新成功,返回nil
type DefaultLogger ¶
type DefaultLogger struct {
// contains filtered or unexported fields
}
DefaultLogger 是默认的日志实现 它封装了标准库的 log.Logger,并添加了日志级别控制
func NewDefaultLogger ¶
func NewDefaultLogger() *DefaultLogger
NewDefaultLogger 创建一个新的默认日志器 它初始化日志级别为 Info,并将输出设置为标准输出
func (*DefaultLogger) SetLevel ¶
func (l *DefaultLogger) SetLevel(level LogLevel)
SetLevel 设置日志记录的级别 这允许在运行时动态调整日志的详细程度
func (*DefaultLogger) SetOutput ¶
func (l *DefaultLogger) SetOutput(output io.Writer)
SetOutput 设置日志输出的目标 这允许将日志重定向到不同的输出,如文件或网络流
type Document ¶
type Document struct {
// contains filtered or unexported fields
}
Document 结构体表示数据库中的一个文档
type Logger ¶
type Logger interface { // Info 记录一般信息日志 Info(v ...interface{}) // Warn 记录警告日志 Warn(v ...interface{}) // Error 记录错误日志 Error(v ...interface{}) // Debug 记录调试信息 Debug(v ...interface{}) // SetLevel 设置日志记录的级别 SetLevel(level LogLevel) // SetOutput 设置日志输出的目标 SetOutput(output io.Writer) }
Logger 接口定义了日志系统应该实现的方法 这个接口允许我们在将来轻松地替换日志实现,而不影响其他代码
type Trie ¶
type Trie struct {
// contains filtered or unexported fields
}
Trie 结构体表示整个Trie树
func (*Trie) FuzzySearch ¶
FuzzySearch 在 Trie 中执行模糊搜索