2

假设您不知道 leveldb 数据库中的确切键。

我尝试插入 3 个键并在键范围上使用 GetApproximateSizes,结果始终为零。

那么如何检查 leveldb 中是否有任何键?

4

2 回答 2

2

我们通过更高级别的 API levelUP在 NodeJS 项目中使用 leveldb 。使用 levelUP API,您可以请求所有键的流,并设置limit=1将响应限制为最多一个键。如果数据库为空,您将获得一个空流,否则您将获得一个只有一个项目的流。

var empty = true;
db.createReadStream(db, {
    keys: true,
    values: false,
    limit: 1
}.on('data', function(data) {
    empty = false;
}.on('end', function() {
    console.log('db is ' + (empty ? 'empty' : 'not empty')); 
});

我们在 npm 模块level-is-empty中使用了这种技术。

由于您需要使用 leveldb 的本机 API 的解决方案,因此我研究了 levelUP 是如何实现createReadStream()API 的。

在 levelUP 中,createReadStream 是使用迭代器实现的

在 levelDOWN 中,本地 Iterator 实例在此处创建。调用next它会告诉您迭代器是否有更多数据或已完成

我在这里找到了如何使用本机 leveldb 迭代器的示例

显然,迭代器方法Valid()告诉你是否还有更多的键要读取。因此,通过简单地调用 SeekToFirst(),然后调用 Valid(),您应该能够找出数据库中是否有任何键。

这是我最好的猜测(代码未经测试,我手头没有 C 编译器)

leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
it->SeekToFirst();
bool isEmpty = !(it->Valid());
delete it;
于 2015-06-18T16:23:51.337 回答
1

您不能只使用 leveldb 扫描并打印所有键和值。例如,要打印数据库中的所有键和值,您可以执行以下操作:

  leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
  for (it->SeekToFirst(); it->Valid(); it->Next()) {
    cout << it->key().ToString() << ": "  << it->value().ToString() << endl;
  }
  assert(it->status().ok());  // Check for any errors found during the scan
  delete it;

现在 GetApproximateSizes 给出零值,因为您刚刚插入了 3 个键并且它们仍在内存中(memtable)并且尚未到达文件系统。一旦内存表已满(默认为 4MB),它就会在级别 0 中创建第一个文件。因此它在更大的数据库和更大的键范围上更有用。

在您的情况下,文件系统中唯一存在数据的地方是重做日志,如果您的键是字符串,您可以通过在 db 目录中调用“strings logfile”(在 linux 中)来快速检查以打印出您的字符串部分键作为确认数据已进入的快速方法。

于 2013-10-27T04:55:20.527 回答