|
|
@ -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. **错误处理**: |
|
|
|
- 如果迭代过程中出现错误,记录错误信息,便于调试。 |
|
|
|
|
|
|
|
此方法通过范围查询机制提升了效率,同时确保了结果的准确性。 |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|