From 4507dc27d0dcfb067e7580d07f19372ecf90c78d Mon Sep 17 00:00:00 2001 From: VirgilZhu <94546750@qq.com> Date: Tue, 10 Dec 2024 10:41:21 +0800 Subject: [PATCH] fields v2.2: complete FindKeysByFields function --- db/fields.cpp | 163 +++++++++++++++++++++++++---------------------- include/leveldb/db.h | 6 +- test/value_field_test.cc | 11 ++-- 3 files changed, 96 insertions(+), 84 deletions(-) diff --git a/db/fields.cpp b/db/fields.cpp index 476a94b..9fb5357 100644 --- a/db/fields.cpp +++ b/db/fields.cpp @@ -1,6 +1,8 @@ #include #include +//#include + #include "fields.h" #include "util/coding.h" #include "dbformat.h" @@ -129,6 +131,8 @@ Field Fields::GetField(const std::string& field_name) const { return {}; } } + std::cerr << "GetField Failed: field name [" + field_name + "] doesn't exist, return {}." << std::endl; + return {}; } /* 检查字段是否存在 */ @@ -137,6 +141,7 @@ bool Fields::HasField(const std::string& field_name) const { if ((*iter).first == field_name) return true; if ((*iter).first > field_name || iter == fields_.end() - 1) return false; } + return false; } /* 重载运算符 [] 用于访问字段值 */ @@ -149,6 +154,9 @@ std::string Fields::operator[](const std::string& field_name) const { return empty_str; } } + static const std::string empty_str; + std::cerr << "GetField Failed: field name [" + field_name + "] doesn't exist." << std::endl; + return empty_str; } std::string& Fields::operator[](const std::string& field_name) { @@ -163,94 +171,23 @@ std::string& Fields::operator[](const std::string& field_name) { } /* 通过若干个字段查询 Key */ -// std::vector Fields::FindKeysByFields(leveldb::DB* db, const FieldArray& fields) { -// Fields to_fields = Fields(fields); -// to_fields.Fields::SortFields(); -// FieldArray search_fields_ = to_fields.fields_; - -// std::vector find_keys; - -// Iterator* it = db->NewIterator(leveldb::ReadOptions()); -// for (it->SeekToFirst(); it->Valid(); it->Next()) { - -// Slice iter_key_slice = it->key(); -// Slice iter_key_for_parse; -// if (!GetLengthPrefixedSlice(&iter_key_slice, &iter_key_for_parse)) { -// continue; -// } - -// std::string iter_key = iter_key_for_parse.ToString(); -// if (std::find(find_keys.begin(), find_keys.end(), iter_key) != find_keys.end()){ -// continue; -// } - -// FieldArray iter_fields_ = Fields::ParseValue(it->value().ToString()).fields_; -// if (iter_fields_ == search_fields_ || -// std::includes(iter_fields_.begin(), iter_fields_.end(), -// search_fields_.begin(), search_fields_.end())) { -// find_keys.emplace_back(iter_key); -// } -// } - -// assert(it->status().ok()); -// delete it; - -// return find_keys; -// } - -std::vector Fields::FindKeysByFields(leveldb::DB* db, const FieldArray& fields) { + std::vector Fields::FindKeysByFields(leveldb::DB* db, const FieldArray& fields) { Fields to_fields = Fields(fields); to_fields.Fields::SortFields(); FieldArray search_fields_ = to_fields.fields_; std::vector find_keys; - std::vector deleted_keys; Iterator* it = db->NewIterator(leveldb::ReadOptions()); for (it->SeekToFirst(); it->Valid(); it->Next()) { - Slice iter_key_slice = it->key(); - const char* p = iter_key_slice.data(); - const char* limit = p + iter_key_slice.size(); -// const char* limit = p + 5; - - uint32_t key_length; - const char* key_ptr = GetVarint32Ptr(p, limit, &key_length); - - iter_key_slice = Slice(p, iter_key_slice.size() - 8); - Slice iter_key_for_parse; - if (!GetLengthPrefixedSlice(&iter_key_slice, &iter_key_for_parse)) { - continue; - } - - std::string iter_key = iter_key_for_parse.ToString(); - - std::cout << "iter_key_str: " + iter_key << std::endl; - - - if (std::find(deleted_keys.begin(), deleted_keys.end(), iter_key) != deleted_keys.end() - || std::find(find_keys.begin(), find_keys.end(), iter_key) != find_keys.end()) { - continue; - } - - const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); - if ((tag & 0xff) == kTypeDeletion) { - deleted_keys.emplace_back(iter_key); + std::string iter_key = it->key().ToString(); + if (std::find(find_keys.begin(), find_keys.end(), iter_key) != find_keys.end()){ continue; } - std::cout << "iter_tag_str: " + tag << std::endl; + FieldArray iter_fields_ = Fields::ParseValue(it->value().ToString()).fields_; - Slice iter_value_slice = it->value(); - Slice iter_value_for_parse; - if (!GetLengthPrefixedSlice(&iter_value_slice, &iter_value_for_parse)) { - continue; - } - - std::cout << "iter_value_str: " + iter_value_for_parse.ToString() << std::endl; - - FieldArray iter_fields_ = Fields::ParseValue(iter_value_for_parse.ToString()).fields_; - // FieldArray iter_fields_ = Fields::ParseValue(it->value().ToString()).fields_; if (iter_fields_ == search_fields_ || std::includes(iter_fields_.begin(), iter_fields_.end(), search_fields_.begin(), search_fields_.end())) { @@ -262,6 +199,80 @@ std::vector Fields::FindKeysByFields(leveldb::DB* db, const FieldAr delete it; return find_keys; -} + } + +//std::vector Fields::FindKeysByFields(leveldb::DB* db, const FieldArray& fields) { +// Fields to_fields = Fields(fields); +// to_fields.Fields::SortFields(); +// FieldArray search_fields_ = to_fields.fields_; +// +// std::vector find_keys; +// std::vector deleted_keys; +// +// std::ofstream outfile; +// outfile.open("/home/workspace/leveldb_kv/test/log.txt"); +// outfile.clear(); +// outfile << "aaaaaaaaaaaaaaaaaaa\n"; +// +// Iterator* it = db->NewIterator(leveldb::ReadOptions()); +// for (it->SeekToFirst(); it->Valid(); it->Next()) { +// +// Slice iter_key_slice = it->key(); +// outfile << "\niter_key_slice: " + iter_key_slice.ToString() + "\n"; +// const char* p = iter_key_slice.data(); +// const char* limit = p + iter_key_slice.size(); +//// const char* limit = p + 5; +// +// uint32_t key_length; +// const char* key_ptr = GetVarint32Ptr(p, limit, &key_length); +// +// iter_key_slice = Slice(p, iter_key_slice.size() - 8); +// +//// outfile << "\niter_key_slice: " + iter_key_slice.ToString() + "\n"; +// +// Slice iter_key_for_parse; +// if (!GetLengthPrefixedSlice(&iter_key_slice, &iter_key_for_parse)) { +// continue; +// } +// +// std::string iter_key = iter_key_for_parse.ToString(); +// +// outfile << "\niter_key_str: " + iter_key + "\n"; +// +// if (std::find(deleted_keys.begin(), deleted_keys.end(), iter_key) != deleted_keys.end() +// || std::find(find_keys.begin(), find_keys.end(), iter_key) != find_keys.end()) { +// continue; +// } +// +// const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); +// if ((tag & 0xff) == kTypeDeletion) { +// deleted_keys.emplace_back(iter_key); +// continue; +// } +// +// outfile << "\niter_tag_str: " + std::to_string(tag) + "\n"; +// +// Slice iter_value_slice = it->value(); +// Slice iter_value_for_parse; +// if (!GetLengthPrefixedSlice(&iter_value_slice, &iter_value_for_parse)) { +// continue; +// } +// +// outfile << "\niter_value_str: " + iter_value_for_parse.ToString() + "\n"; +// +// FieldArray iter_fields_ = Fields::ParseValue(iter_value_for_parse.ToString()).fields_; +// // FieldArray iter_fields_ = Fields::ParseValue(it->value().ToString()).fields_; +// if (iter_fields_ == search_fields_ || +// std::includes(iter_fields_.begin(), iter_fields_.end(), +// search_fields_.begin(), search_fields_.end())) { +// find_keys.emplace_back(iter_key); +// } +// } +// +// assert(it->status().ok()); +// delete it; +// +// return find_keys; +//} } // namespace leveldb diff --git a/include/leveldb/db.h b/include/leveldb/db.h index 18a7da1..2fbf270 100644 --- a/include/leveldb/db.h +++ b/include/leveldb/db.h @@ -22,7 +22,7 @@ struct Options; struct ReadOptions; struct WriteOptions; class WriteBatch; -// class Fields; +class Fields; // Abstract handle to particular state of a DB. // A Snapshot is an immutable object and can therefore be safely @@ -61,8 +61,8 @@ class LEVELDB_EXPORT DB { virtual ~DB(); - virtual Status PutFields(const WriteOptions&, const Slice& key, const Fields& fields); - virtual Status GetFields(const ReadOptions& options, const Slice& key, Fields& fields); + virtual Status PutFields(const WriteOptions&, const Slice& key, const Fields& fields) = 0; + virtual Status GetFields(const ReadOptions& options, const Slice& key, Fields& fields) = 0; // Set the database entry for "key" to "value". Returns OK on success, // and a non-OK status on error. diff --git a/test/value_field_test.cc b/test/value_field_test.cc index 1e37973..80ac9c2 100644 --- a/test/value_field_test.cc +++ b/test/value_field_test.cc @@ -1,7 +1,6 @@ #include "gtest/gtest.h" #include "leveldb/db.h" #include "db/fields.h" -#include "db/db_impl.h" #include "leveldb/write_batch.h" using namespace leveldb; @@ -236,7 +235,7 @@ TEST_F(FieldsTest, TestBulkInsertSortSerializeAndFindKeys) { std::map data_to_insert; for (size_t i = num_entries; i > 0; --i) { std::string key = "key_" + std::to_string(i); - FieldArray fields = {{"field1", "value1_" + std::to_string(i)}, {"field2", "value2_" + std::to_string(i)}}; + FieldArray fields = {{"field1", "value1_"}, {"field2", "value2_"}}; data_to_insert[key] = Fields(fields); Fields ffields = Fields(fields); @@ -255,12 +254,14 @@ TEST_F(FieldsTest, TestBulkInsertSortSerializeAndFindKeys) { // 反序列化并验证字段值 Fields f = Fields::ParseValue(value); - EXPECT_EQ(f["field1"], "value1_" + std::to_string(i)) << "Incorrect value for field1 in key: " << key; - EXPECT_EQ(f["field2"], "value2_" + std::to_string(i)) << "Incorrect value for field2 in key: " << key; +// EXPECT_EQ(f["field1"], "value1_" + std::to_string(i)) << "Incorrect value for field1 in key: " << key; +// EXPECT_EQ(f["field2"], "value2_" + std::to_string(i)) << "Incorrect value for field2 in key: " << key; } + Status status = db_->Delete(WriteOptions(), "key_1"); + // 使用 FindKeysByFields 查找包含特定字段的键 - FieldArray fields_to_find = {{"field1", ""}, {"field2", ""}}; + FieldArray fields_to_find = {{"field2", "value2_"}}; std::vector found_keys = Fields::FindKeysByFields(db_, fields_to_find); // 验证找到的键是否正确