Kaynağa Gözat

Fix some code and express base on handout

main
kevinyao0901 1 hafta önce
ebeveyn
işleme
c5d348dae9
2 değiştirilmiş dosya ile 66 ekleme ve 44 silme
  1. +36
    -33
      README.md
  2. +30
    -11
      db/db_impl.cc

+ 36
- 33
README.md Dosyayı Görüntüle

@ -291,52 +291,55 @@ Status DBImpl::CreateIndexOnField(const std::string& fieldName) {
### 3. **二级索引的查询**
在查询二级索引时,我们不再使用遍历所有索引的方式,而是直接利用 `Get` 方法根据索引键查找对应的值。这种方法避免了遍历所有索引的开销,提高了查询效率
在查询二级索引时,基于二级索引,通过范围查询从 LevelDB 数据库中检索与指定字段名 (`fieldName`) 相关联的所有值。
#### 核心代码:
```cpp
// 查询通过字段名索引的所有值
std::vector<std::string> DBImpl::QueryByIndex(const std::string& fieldName) {
std::vector<std::string> 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. **错误处理**:
- 如果迭代过程中出现错误,记录错误信息,便于调试。
此方法通过范围查询机制提升了效率,同时确保了结果的准确性。
---

+ 30
- 11
db/db_impl.cc Dosyayı Görüntüle

@ -1770,20 +1770,39 @@ Status DBImpl::DeleteIndex(const std::string& fieldName) {
// Query by index (retrieve all values indexed by a field)
std::vector<std::string> DBImpl::QueryByIndex(const std::string& fieldName) {
std::vector<std::string> 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;
}

Yükleniyor…
İptal
Kaydet