From c5d348dae92401b791dfccee8ce554d9740c31f6 Mon Sep 17 00:00:00 2001 From: kevinyao0901 Date: Sun, 5 Jan 2025 13:34:59 +0800 Subject: [PATCH] Fix some code and express base on handout --- README.md | 69 +++++++++++++++++++++++++++++++---------------------------- db/db_impl.cc | 41 +++++++++++++++++++++++++---------- 2 files changed, 66 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 540a8c9..0306d24 100644 --- a/README.md +++ b/README.md @@ -291,52 +291,55 @@ Status DBImpl::CreateIndexOnField(const std::string& fieldName) { ### 3. **二级索引的查询** -在查询二级索引时,我们不再使用遍历所有索引的方式,而是直接利用 `Get` 方法根据索引键查找对应的值。这种方法避免了遍历所有索引的开销,提高了查询效率。 +在查询二级索引时,基于二级索引,通过范围查询从 LevelDB 数据库中检索与指定字段名 (`fieldName`) 相关联的所有值。。 #### 核心代码: ```cpp // 查询通过字段名索引的所有值 std::vector DBImpl::QueryByIndex(const std::string& fieldName) { - std::vector results; + function QueryByIndex(fieldName): + results = [] // 用于存储查询结果 - leveldb::ReadOptions read_options; - - // 直接通过 Get 方法查找与 fieldName 相关的索引 - std::string indexKey = fieldName; // fieldName 就是索引键 - std::string value; - Status s = indexDb_->Get(read_options, Slice(indexKey), &value); - - // 如果成功找到对应的值,将其加入结果中 - if (s.ok()) { - results.push_back(value); - } else if (s.IsNotFound()) { - // 如果没有找到,返回空结果 - std::cerr << "Index key not found: " << indexKey << std::endl; - } else { - // 处理其他错误 - std::cerr << "Error querying index: " << s.ToString() << std::endl; - } + // 初始化读取选项和迭代器 + create ReadOptions read_options + create Iterator it from indexDb_ using read_options - return results; -} -``` + // 遍历所有键值对,从 fieldName 开始 + for it.Seek(fieldName) to it.Valid(): + key = current key from it + value = current value from it -#### 关键点说明: + // 如果键匹配并且值非空,将其加入结果列表 + if key equals fieldName and value is not empty: + add value to results -- **`Get` 查询**:直接通过 `Get` 方法查找 `indexDb_` 中与 `fieldName` 对应的索引键。这样我们避免了遍历整个索引数据库,直接根据给定的键获取对应的值,查询效率得到了显著提高。 - -- **查询逻辑**:我们使用 `fieldName` 作为索引键,执行查询操作。如果查询成功,我们将返回的值(即主数据库的键)添加到结果集中。如果查询失败(例如索引键不存在),我们会输出相应的错误信息。 + // 检查迭代器的状态是否正常 + if iterator status is not OK: + log error with status message -- **结果处理**:如果查询成功,返回的值将作为结果添加到返回的 `vector` 中;如果查询失败,系统会输出相应的错误信息,确保在查询操作中的透明度和可维护性。 + return results -#### 优点: - -- **提高查询效率**:通过直接使用 `Get` 方法,我们不再需要遍历所有索引,这大大提升了查询的效率。 -- **简化代码**:由于查询逻辑简化为一次 `Get` 调用,代码更加简洁易懂,减少了不必要的复杂性。 -- **一致性保障**:通过 `Get` 查询,直接从索引数据库中获取与特定字段名相关的索引值,确保了结果的准确性。 +} +``` -通过这种方式,我们优化了二级索引的查询方法,提高了系统在处理索引查询时的性能,并且保证了查询结果的一致性和准确性。 +1. **输入与输出**: + - 输入:`fieldName`(目标字段名)。 + - 输出:`results`(包含所有匹配值的列表)。 +2. **逻辑流程**: + - 使用 `ReadOptions` 初始化读取配置,并创建一个迭代器。 + - 调用 `Seek(fieldName)` 将迭代器定位到目标字段的起始位置。 + - 遍历满足条件的键值对: + - 如果键等于目标字段名,并且值非空,将值添加到结果列表。 + - 在遍历结束后,检查迭代器的状态以捕捉可能的错误。 +3. **优势**: + - 使用迭代器实现范围查询(`Seek` 方法快速定位)。 + - 避免全表扫描,提高查询效率。 + - 针对多值字段支持查询返回多个结果。 +4. **错误处理**: + - 如果迭代过程中出现错误,记录错误信息,便于调试。 + +此方法通过范围查询机制提升了效率,同时确保了结果的准确性。 --- diff --git a/db/db_impl.cc b/db/db_impl.cc index c82da81..727a021 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -1770,20 +1770,39 @@ Status DBImpl::DeleteIndex(const std::string& fieldName) { // Query by index (retrieve all values indexed by a field) std::vector DBImpl::QueryByIndex(const std::string& fieldName) { std::vector results; - leveldb::ReadOptions read_options; - std::string value; - // 使用 Get 方法从 indexDb_ 中获取与 fieldName 对应的值 - leveldb::Status s = indexDb_->Get(read_options, fieldName, &value); + // 假设您有一个存储索引的数据库 indexDb_ + // leveldb::ReadOptions read_options; + // std::string value; - if (s.ok() && !value.empty()) { - // 如果获取的值非空,则将其添加到结果列表 - results.push_back(value); - } else if (!s.ok()) { - std::cerr << "Error querying index for field: " << fieldName - << ". Status: " << s.ToString() << std::endl; - } + // // 使用 Get 方法从 indexDb_ 中获取与 fieldName 对应的值 + // leveldb::Status s = indexDb_->Get(read_options, fieldName, &value); + + // if (s.ok() && !value.empty()) { + // // 如果获取的值非空,则将其添加到结果列表 + // results.push_back(value); + // } else if (!s.ok()) { + // // 如果查询发生错误,则处理错误 + // std::cerr << "Error querying index for field: " << fieldName + // << ". Status: " << s.ToString() << std::endl; + // } + // return results; + leveldb::ReadOptions read_options; + leveldb::Iterator* it = indexDb_->NewIterator(read_options); + for (it->Seek(fieldName); it->Valid(); it->Next()) { + std::string key = it->key().ToString(); + std::string value = it->value().ToString(); + // 仅将非空值添加到结果中 + if (key == fieldName && !value.empty()) { + results.push_back(value); + } + } + if (!it->status().ok()) { + // 处理查询错误 + std::cerr << "Error querying index: " << it->status().ToString() << std::endl; + } + delete it; return results; }