2

I'm using RocksDbSharp library, which is implementation of RocksDb from facebook in C#. I would like to filter my records by part of a key, but unfortunately, I don't see an option how to do that. Here is sample code:

static void Main(string[] args)
{
    string directory = @"C:\Path\To\RocksDB\Storage";

    DbOptions options = new DbOptions().SetCreateIfMissing(true);

    using (RocksDb rocksDb = RocksDb.Open(options, directory))
    {
        rocksDb.Put("AAAAB", "Test 1");
        rocksDb.Put("AAABB", "Test 2");
        rocksDb.Put("AABBB", "Test 3");
        rocksDb.Put("ABBBB", "Test 4");
        rocksDb.Put("BBBBB", "Test 5");

        List<string> keys = new List<string>();

        using (Iterator iterator = rocksDb.NewIterator())
        {
            iterator.Seek("AAB");

            while (iterator.Valid())
            {
                keys.Add(iterator.StringKey());

                iterator.Next();
            }
        }

        Console.WriteLine(string.Join(", ", keys));
        Console.ReadLine();
    }
}

The output is:

AABBB, ABBBB, BBBBB

How can I change it, so the output would be only AABBB? I read Iterator wiki and Prefix Seek API, that I can do that setting prefix_same_as_start to true:

If no key of the prefix equals or is larger than lookup_key, or after calling one or more Next(), we finish all keys for the prefix, we might return Valid()=false, or any key that is larger than the previous key, depending on whether ReadOptions.prefix_same_as_start=true.

Also, it is explain in this ticket:

If you only want keys starting with prefix 002, use the read_options.prefix_same_as_start, which only shows keys with the same prefix as that when you did the seek.

How can I set this property to true? If you check the implementation of ReadOptions class, you won't find anything to set this property. Do I have any other options to filter keys?

Peska
  • 3,980
  • 3
  • 23
  • 40

1 Answers1

1

To retrieve via prefix, you should create a prefix extractor first.

Options options;
options.prefix_extractor.reset(NewFixedPrefixTransform(<Length of the prefix>));

and open the DB using these options.

Set prefix_same_as_start to true in ReadOptions.

The following snippet might help you out, (Written in C++ though)

int main()
{
    DB *db;
    Options options;
    options.IncreaseParallelism();
    options.OptimizeLevelStyleCompaction();
    options.create_if_missing = true;
    options.prefix_extractor.reset(NewFixedPrefixTransform(3));

    Status s = DB::Open(options, kDBPath, &db);
    assert(s.ok());

    s = db->Put(WriteOptions(), "AAAAB", "value1");
    assert(s.ok());    
    s = db->Put(WriteOptions(), "AAABB", "value2");
    assert(s.ok());
    s = db->Put(WriteOptions(), "AABBB", "value3");
    assert(s.ok());
    s = db->Put(WriteOptions(), "ABBBB", "value4");
    assert(s.ok());
    s = db->Put(WriteOptions(), "BBBBB", "value5");
    assert(s.ok());

    ReadOptions read_options;
    read_options.prefix_same_as_start = true;

    Iterator *iter = db->NewIterator(read_options);
    iter->Seek("AAB");

    while (iter->Valid())
    {
        printf("key %s\n", iter->key().ToString().c_str());
        iter->Next();
    }

    delete iter;
    delete db;
    return 0;
}

Since rocksdb is written in c++, you might want to write a wrapper function for prefix_same_as_start if not present and include it. For wrapper function examples, in rocksdb native code, there are files c.cc/c.h that writes wrapper functions in C for various rocksdb options. You can write one in C# to meet your requirements. :)

  • 1
    Thanks, but I know how it should be done in C++. Problem is with C#. Further investigation takes me to this file: https://github.com/warrenfalk/rocksdb-sharp/blob/master/RocksDbSharp/Native.Raw.cs. It states, that this library was build with old version of RocksDb, that didn't have `prefix_same_as_start` option yet. I will try to contact owner and ask him, for a new build. – Peska Sep 25 '18 at 06:04