2012-05-07 8 views
2

key-prefixで反復するためにleveldbを使用してキー列挙子を実装する効率的な方法を探しています。キーはバイト配列です(そして、dbはデフォルトのバイト配列比較を使用しているので、特定の接頭辞を持つすべてのキーは順番に格納/取得されます)。私はイテレータがキー接頭辞を取って、接頭辞。LevelDB:キープレフィックスで列挙するイテレータを実装する

デフォルトのdbイテレータを継承するか、範囲内の最初のキーを探して(それが何であるかを知る必要があります)、接頭辞で始まるすべてのスライスを検証して返します(オーバーライドするmovenextか何か)?またはこれを実装するより効率的な方法がありますか?

誰かがこれを既に解決しているかどうかを知り、コードや一般的なアイデアを共有することができます。私はこれをC++/CLIから試していますが、どの言語で実装しても役に立ちます。

ありがとうございました。 -raj。

答えて

2

コンパレータは、キーが異なるかどうかを判断するために使用されます。オーバーロードすると、データベースをスキャンするときにプレフィックスだけでなく、フルキーを比較できる必要があるためです。イテレータをオーバーロードする必要はありません。キーがleveldbで整理されていれば、異なる接頭辞を持つキーに遭遇した場合、すでに範囲外になっていることがわかります。あなたは通常どおりと限り、あなたのキーが適切に評価されるようあなたはただあなたが正しい結果を得る必要があり、イテレータを使用することができます。

void ScanRecordRange(const leveldb::Slice& startSlice, const leveldb::Slice& endSlice) 
{ 
    // Get a database iterator 
    shared_ptr<leveldb::Iterator> dbIter(_database->NewIterator(leveldb::ReadOptions())); 

    // Possible optimization suggested by Google engineers 
    // for critical loops. Reduces memory thrash. 
    for(dbIter->Seek(startSlice); dbIter->Valid() && _options.comparator->Compare(dbIter->key(), endSlice)<=0 ;dbIter->Next()) 
    {     
     // Read the record 
     if(!dbIter->value().empty()) 
     { 
      leveldb::Slice keySlice(dbIter->key()); 
      leveldb::Slice dataSlice(dbIter->data()); 
      // TODO: process the key/data 

     } 
    } 
} 
+0

ありがとう:
は、それはstartsWithメソッドによって返された範囲内で使用されています。はい、私はleveldbのドキュメントで同様の例を見ました。これは範囲[startSlice、endSlice]を取得します。しかし、私の「接頭辞」問題はendSliceを知りませんし、私のキーもすべて同じサイズ/長さではないということでした。しかし、あなたが言ったように、私はデフォルトのイテレータを使うことができ、<=の完全キーを比較するのではなく、入力プレフィックスと同じ長さの部分を取り、入力と等しいかどうかを比較する必要があります。 leveldbが最適な実装でこの関数を提供したかったらいいです。 :) – user392005

+0

すべてのキーを読むまで反復することができる、希望の接頭辞で 'endKey'を構築することができます。 0xC7D8FFFF、プレフィックスはC7D8、FFFFはキーの残りの部分です。開始キーは0xC7D80000になります。しかし、私はなぜあなたのキーの長さが異なるのか分からない、あなたは文字列を使用していますか?その場合は、CityHashを使用して文字列をハッシュし、固定長の64ビットまたは128ビットのキーを使用する必要があります。キーをハッシュすると**これはもっと簡単に**できます! – Kiril

+0

私のキーはバイト配列です。私はleveldbをpatricia trieとして使用しているため、ノードのツリーを特定の基準で格納/取得しているので、直接の子どもが祖父母の前にディスクに/から順番に格納/検索されます。接頭辞などとして親キー情報を含むようにキーが長くなる! – user392005

0

私はmy LevelDB wrapperに接頭辞イテレータを持っています。応答、Lirikため

int count = 0; 
for (auto& en: ldb.startsWith (std::string ("prefix"))) {++count;} 
+0

これは、公式のサンプルコードと同じ弱点があります。データベースにカスタムコンパレータがある場合は、ここでエンドコンパウンドの比較方法とは異なる方法でエンドキーを比較しています。 –

+0

@AndyDent、気づいてくれてありがとう。この機能が必要な場合は、機能リクエストを送信してください。 – ArtemGr

+0

難しい方法に気づいた - 私のカスタムコードをコンパイルする前に約3つの例を伝播し、私のコンパイラとiteratorRangeが失敗した;-) –

関連する問題