Ключ LevelDB, значение из csv

У меня есть огромная база данных CSV-файлов из ~ 5 миллионов строк с полями ниже

start_ip,end_ip,country,city,lat,long 

Я сохраняю их в LevelDB, используя start_ip в качестве ключа и rest в качестве значения.

Как я могу получить записи для ключей, где

( ip_key > start_ip and ip_key < end_ip )

Любое альтернативное решение.


person Ketan Khairnar    schedule 01.02.2012    source источник


Ответы (1)


Я предполагаю, что ваши ключи представляют собой хэш-значения IP-адреса, а хэши представляют собой 64-битные целые числа без знака, но если это не так, просто измените приведенный ниже код, чтобы учесть правильные ключи.

void MyClass::ReadRecordRange(const uint64 startRange, const uint64 endRange)
{
    // Get the start slice and the end slice
    leveldb::Slice startSlice(static_cast<const char*>(static_cast<const void*>(&startRange)), sizeof(startRange));
    leveldb::Slice endSlice(static_cast<const char*>(static_cast<const void*>(&endRange)), sizeof(endRange));

    // 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())
    {
        // get the key
        dbIter->key().data();

        // get the value
        dbIter->value().data();

        // TODO do whatever you need to do with the key/value you read
    }
}

Обратите внимание, что _options — это те же leveldb::Options, с помощью которых вы открыли экземпляр базы данных. Вы хотите использовать компаратор, указанный в параметрах, чтобы порядок, в котором вы читаете записи, совпадал с порядком в базе данных.

Если вы не используете boost или tr1, вы можете либо использовать что-то другое, похожее на shared_ptr, либо просто удалить leveldb::Iterator самостоятельно. Если вы не удалите итератор, вы потеряете память и получите утверждения в режиме отладки.

person Kiril    schedule 01.02.2012
comment
я использую привязки leveldb-jni из fusesource(github.com/fusesource/leveldbjni). Хотя это не вопрос логики. Я использую байты ipv4/ipv6 в ключах, и мне нужно выяснить, принадлежит ли входной запрос некоторому диапазону. - person Ketan Khairnar; 02.02.2012
comment
Ах, хорошо... ну, я знаком только с библиотекой C++, поэтому я не знаю, как это сделать на Java, но я только что посмотрел исходный код, и кажется, что вам просто нужно получить DBIterator, вызвав метод iterator(...) БД. С этого момента я предполагаю, что вы можете использовать ту же логику, что и выше. Если вы просто хотите выяснить, принадлежит ли ключ к какому-то диапазону, используйте NativeComparator, чтобы проверить, находится ли ключ в заданном диапазоне. - person Kiril; 02.02.2012
comment
Благодарю. Хотя это по-другому. Я хочу найти диапазон, к которому принадлежит ввод; и я сохраняю только начало диапазона в качестве ключа. нет перекрывающихся диапазонов, поэтому это должно быть хорошо. - person Ketan Khairnar; 02.02.2012
comment
Итак, это отвечает на ваш вопрос? Как я вижу, в вашей базе данных есть ключи [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], и вы вызываете ReadRecordRange(4, 7), он будет читать ключи [4, 5, 6, 7]. Это то поведение, которое вы хотите, верно? - person Kiril; 02.02.2012
comment
Нет, скажем, мои ключи [1,3,5,7,9], поэтому для ключа 4 мне нужно получить запись с ключом == 3. ключ 1 предназначен для всех элементов в диапазоне 1-2, то же самое для ключа 7, который сопоставляется со всеми элементами в диапазоне 7-8. Поскольку все мои записи уже отсортированы и нет перекрывающихся диапазонов, все работало, как показано ниже. Я ищу с помощью dbiterator, а затем проверяю предыдущую запись. Это сработало! - person Ketan Khairnar; 03.02.2012
comment
@Ketan, да, это работает :)... дайте мне знать, если мой ответ указал вам правильное направление. - person Kiril; 03.02.2012