mirror of
https://github.com/YuhangQ/InvoDB.git
synced 2025-01-26 22:50:56 +00:00
完善数据库查询算法
This commit is contained in:
parent
99265240b8
commit
6c538caaab
@ -11,4 +11,4 @@ include_directories(./invodb)
|
|||||||
|
|
||||||
add_executable(InvoDB
|
add_executable(InvoDB
|
||||||
invodb/main.cpp
|
invodb/main.cpp
|
||||||
invodb/main.h invodb/file/page_manager.cpp invodb/file/page_manager.h invodb/models/collection.cpp invodb/models/collection.h invodb/file/storage_page.cpp invodb/file/storage_page.h invodb/utils/logger.h invodb/utils/uuid.h invodb/btree/node.h invodb/btree/btree.h invodb/index/index.cpp invodb/index/index.h invodb/btree/list.h invodb/index/query.cpp invodb/index/query.h invodb/models/cache.h)
|
invodb/main.h invodb/file/page_manager.cpp invodb/file/page_manager.h invodb/collection/collection.cpp invodb/collection/collection.h invodb/file/storage_page.cpp invodb/file/storage_page.h invodb/utils/logger.h invodb/utils/uuid.h invodb/btree/node.h invodb/btree/btree.h invodb/btree/list.h invodb/collection/query.cpp invodb/utils/cache.h invodb/collection/index.cpp)
|
||||||
|
@ -8,14 +8,18 @@
|
|||||||
#include "btree/node.h"
|
#include "btree/node.h"
|
||||||
#include "utils/uuid.h"
|
#include "utils/uuid.h"
|
||||||
|
|
||||||
|
#define M_SIZE 1000 / (K_SIZE + 4)
|
||||||
|
|
||||||
template<typename KT, int K_SIZE>
|
template<typename KT, int K_SIZE>
|
||||||
class BTree {
|
class BTree {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
static std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>> getNode(const int &index);
|
||||||
|
|
||||||
BTree(const int& address);
|
BTree(const int& address);
|
||||||
void insert(const KT &key, const int &value);
|
void insert(const KT &key, const int &value);
|
||||||
void update(const KT &key, const int &value);
|
void update(const KT &key, const int &value);
|
||||||
void remove(const KT &key);
|
void remove(const KT &key);
|
||||||
|
|
||||||
bool exists(const KT &key);
|
bool exists(const KT &key);
|
||||||
int getNodeSize();
|
int getNodeSize();
|
||||||
int find(const KT &key);
|
int find(const KT &key);
|
||||||
@ -37,9 +41,15 @@ private:
|
|||||||
void insertInternal(const KT &key, int curAdd, int lLeafAdd, int rLeafAdd);
|
void insertInternal(const KT &key, int curAdd, int lLeafAdd, int rLeafAdd);
|
||||||
int root;
|
int root;
|
||||||
int n_size;
|
int n_size;
|
||||||
static const int M_SIZE = 1000 / (K_SIZE + 4);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename KT, int K_SIZE>
|
||||||
|
std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>> BTree<KT, K_SIZE>::getNode(const int &index) {
|
||||||
|
return BTreeNode<M_SIZE, KT, K_SIZE>::getNode(index);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename KT, int K_SIZE>
|
template<typename KT, int K_SIZE>
|
||||||
BTree<KT, K_SIZE>::BTree(const int& address) {
|
BTree<KT, K_SIZE>::BTree(const int& address) {
|
||||||
root = address;
|
root = address;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include "file/page_manager.h"
|
#include "file/page_manager.h"
|
||||||
#include "invodb/models/cache.h"
|
#include "invodb/utils/cache.h"
|
||||||
|
|
||||||
template<int M_SIZE, typename KT, int K_SIZE>
|
template<int M_SIZE, typename KT, int K_SIZE>
|
||||||
class BTreeNode {
|
class BTreeNode {
|
||||||
@ -37,6 +37,7 @@ public:
|
|||||||
int save();
|
int save();
|
||||||
bool enough();
|
bool enough();
|
||||||
bool full();
|
bool full();
|
||||||
|
void print();
|
||||||
|
|
||||||
KT keySet[m + 1];
|
KT keySet[m + 1];
|
||||||
int linkSet[m + 1];
|
int linkSet[m + 1];
|
||||||
@ -232,4 +233,19 @@ bool BTreeNode<M_SIZE, KT, K_SIZE>::full() {
|
|||||||
return size == maxCount;
|
return size == maxCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<int M_SIZE, typename KT, int K_SIZE>
|
||||||
|
void BTreeNode<M_SIZE, KT, K_SIZE>::print() {
|
||||||
|
|
||||||
|
printf("----Node: %d-----\n", address);
|
||||||
|
|
||||||
|
for(int i=0; i<size; i++) {
|
||||||
|
std::cout << keySet[i] << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
for(int i=0; i<=size-leaf; i++) {
|
||||||
|
printf("%d ", linkSet[i]);
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
#endif //INVODB_NODE_H
|
#endif //INVODB_NODE_H
|
||||||
|
94
invodb/collection/collection.cpp
Normal file
94
invodb/collection/collection.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
//
|
||||||
|
// Created by YuhangQ on 2021/10/9.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "collection.h"
|
||||||
|
|
||||||
|
BTree<std::string, 32> Collection::colList(1);
|
||||||
|
std::map<std::string, Collection*> Collection::map;
|
||||||
|
|
||||||
|
void Collection::loadCollections() {
|
||||||
|
int cnt = 0;
|
||||||
|
for(auto& key : colList.keySet()) {
|
||||||
|
map.insert(std::make_pair(key, new Collection(key, colList.find(key))));
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
Logger::info<std::string, int>("Successfully load Collections: ", cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection& Collection::createCollection(const std::string &name) {
|
||||||
|
// exist
|
||||||
|
if(map.count(name) != 0) {
|
||||||
|
return *map[name];
|
||||||
|
}
|
||||||
|
colList.insert(name, PageManager::Instance().allocate());
|
||||||
|
Collection *col = new Collection(name, colList.find(name));
|
||||||
|
map.insert(make_pair(name, col));
|
||||||
|
return *col;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection &Collection::getCollection(const std::string &name) {
|
||||||
|
if(map.count(name) == 0) {
|
||||||
|
throw "no such collection";
|
||||||
|
}
|
||||||
|
return *map[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection::Collection(const std::string &name, const int &firstPage) {
|
||||||
|
Logger::info<std::string, std::string>("load Collection: ", name);
|
||||||
|
index = new BTree<std::string, 128>(firstPage);
|
||||||
|
if(!index->exists("__INVO_ID__")) {
|
||||||
|
index->insert("__INVO_ID__", PageManager::Instance().allocate());
|
||||||
|
}
|
||||||
|
uuid = new BTree<std::string, 32>(index->find("__INVO_ID__"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Collection::insert(nlohmann::json &json) {
|
||||||
|
|
||||||
|
if(json["__INVO_ID__"].empty()) {
|
||||||
|
json["__INVO_ID__"] = generateUUID();
|
||||||
|
} else {
|
||||||
|
remove(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string id = json["__INVO_ID__"].get<std::string>();
|
||||||
|
int add = PageManager::Instance().saveJSONToFile(json);
|
||||||
|
uuid->insert(id, add);
|
||||||
|
|
||||||
|
//Logger::info<std::string, std::string>("INSERT ", json.dump());
|
||||||
|
|
||||||
|
// add index
|
||||||
|
indexJSON("", json, add);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Collection::remove(const nlohmann::json &json) {
|
||||||
|
if(json["__INVO_ID__"].empty()) {
|
||||||
|
throw "no invo_id";
|
||||||
|
}
|
||||||
|
std::string id = json["__INVO_ID__"].get<std::string>();
|
||||||
|
|
||||||
|
|
||||||
|
int address = uuid->find(id);
|
||||||
|
uuid->remove(id);
|
||||||
|
|
||||||
|
nlohmann::json jsonInDisk = PageManager::Instance().readJSONFromFile(address);
|
||||||
|
|
||||||
|
clearIndex("", json, address);
|
||||||
|
|
||||||
|
PageManager::Instance().release(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Collection::test() {
|
||||||
|
index->print();
|
||||||
|
auto qq = new BTree<std::string, 128>(7);
|
||||||
|
while(true) {
|
||||||
|
std::string q;
|
||||||
|
std::cin >> q;
|
||||||
|
List<int, 4> list(qq->find(q));
|
||||||
|
//list.print();
|
||||||
|
for(auto& add : list.all()) {
|
||||||
|
std::cout << ">> " << PageManager::Instance().readJSONFromFile(add).dump() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,7 @@ class Collection {
|
|||||||
public:
|
public:
|
||||||
void insert(nlohmann::json &json);
|
void insert(nlohmann::json &json);
|
||||||
void remove(const nlohmann::json &json);
|
void remove(const nlohmann::json &json);
|
||||||
|
std::vector<nlohmann::json> query(const nlohmann::json &json);
|
||||||
static void loadCollections();
|
static void loadCollections();
|
||||||
static Collection& getCollection(const std::string& name);
|
static Collection& getCollection(const std::string& name);
|
||||||
static Collection& createCollection(const std::string& name);
|
static Collection& createCollection(const std::string& name);
|
||||||
@ -28,7 +28,6 @@ public:
|
|||||||
void test();
|
void test();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void indexJSON(const std::string prefix, const nlohmann::json &json, const int& address);
|
void indexJSON(const std::string prefix, const nlohmann::json &json, const int& address);
|
||||||
void insertIndex(const std::string indexName, const std::string indexValue, const int& address);
|
void insertIndex(const std::string indexName, const std::string indexValue, const int& address);
|
||||||
void insertIndex(const std::string indexName, double indexValue, const int& address);
|
void insertIndex(const std::string indexName, double indexValue, const int& address);
|
||||||
@ -38,6 +37,15 @@ private:
|
|||||||
void removeIndex(const std::string indexName, double indexValue, const int& address);
|
void removeIndex(const std::string indexName, double indexValue, const int& address);
|
||||||
void removeIndex(const std::string indexName, bool indexValue, const int& address);
|
void removeIndex(const std::string indexName, bool indexValue, const int& address);
|
||||||
|
|
||||||
|
std::set<nlohmann::json> setIntersection(const std::set<nlohmann::json> &a, const std::set<nlohmann::json> &b);
|
||||||
|
std::set<nlohmann::json> setUnion(const std::set<nlohmann::json> &a, const std::set<nlohmann::json> &b);
|
||||||
|
|
||||||
|
std::set<nlohmann::json> innerQuery(const std::string &prefix, const nlohmann::json &json);
|
||||||
|
std::set<nlohmann::json> queryString(const std::string &prefix, const std::string &minValue, const std::string &maxValue, const int &mod = 0);
|
||||||
|
std::set<nlohmann::json> queryNumber(const std::string &prefix, const double &minValue, const double &maxValue, const int &mod = 0);
|
||||||
|
std::set<nlohmann::json> queryBool(const std::string &prefix, const bool &value);
|
||||||
|
std::set<nlohmann::json> queryRange(const std::string &prefix, const nlohmann::json &json);
|
||||||
|
|
||||||
static std::map<std::string, Collection*> map;
|
static std::map<std::string, Collection*> map;
|
||||||
static BTree<std::string, 32> colList;
|
static BTree<std::string, 32> colList;
|
||||||
|
|
@ -1,83 +1,9 @@
|
|||||||
//
|
//
|
||||||
// Created by YuhangQ on 2021/10/9.
|
// Created by YuhangQ on 2021/11/7.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "collection.h"
|
#include "collection.h"
|
||||||
|
|
||||||
BTree<std::string, 32> Collection::colList(1);
|
|
||||||
std::map<std::string, Collection*> Collection::map;
|
|
||||||
|
|
||||||
void Collection::loadCollections() {
|
|
||||||
int cnt = 0;
|
|
||||||
for(auto& key : colList.keySet()) {
|
|
||||||
map.insert(std::make_pair(key, new Collection(key, colList.find(key))));
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
Logger::info<std::string, int>("Successfully load Collections: ", cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection& Collection::createCollection(const std::string &name) {
|
|
||||||
// exist
|
|
||||||
if(map.count(name) != 0) {
|
|
||||||
return *map[name];
|
|
||||||
}
|
|
||||||
colList.insert(name, PageManager::Instance().allocate());
|
|
||||||
Collection *col = new Collection(name, colList.find(name));
|
|
||||||
map.insert(make_pair(name, col));
|
|
||||||
return *col;
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection &Collection::getCollection(const std::string &name) {
|
|
||||||
if(map.count(name) == 0) {
|
|
||||||
throw "no such collection";
|
|
||||||
}
|
|
||||||
return *map[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection::Collection(const std::string &name, const int &firstPage) {
|
|
||||||
Logger::info<std::string, std::string>("load Collection: ", name);
|
|
||||||
index = new BTree<std::string, 128>(firstPage);
|
|
||||||
if(!index->exists("__INVO_ID__")) {
|
|
||||||
index->insert("__INVO_ID__", PageManager::Instance().allocate());
|
|
||||||
}
|
|
||||||
uuid = new BTree<std::string, 32>(index->find("__INVO_ID__"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Collection::insert(nlohmann::json &json) {
|
|
||||||
|
|
||||||
if(json["__INVO_ID__"].empty()) {
|
|
||||||
json["__INVO_ID__"] = generateUUID();
|
|
||||||
} else {
|
|
||||||
remove(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string id = json["__INVO_ID__"].get<std::string>();
|
|
||||||
int add = PageManager::Instance().saveJSONToFile(json);
|
|
||||||
uuid->insert(id, add);
|
|
||||||
|
|
||||||
//Logger::info<std::string, std::string>("INSERT ", json.dump());
|
|
||||||
|
|
||||||
// add index
|
|
||||||
indexJSON("", json, add);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Collection::remove(const nlohmann::json &json) {
|
|
||||||
if(json["__INVO_ID__"].empty()) {
|
|
||||||
throw "no invo_id";
|
|
||||||
}
|
|
||||||
std::string id = json["__INVO_ID__"].get<std::string>();
|
|
||||||
|
|
||||||
|
|
||||||
int address = uuid->find(id);
|
|
||||||
uuid->remove(id);
|
|
||||||
|
|
||||||
nlohmann::json jsonInDisk = PageManager::Instance().readJSONFromFile(address);
|
|
||||||
|
|
||||||
clearIndex("", json, address);
|
|
||||||
|
|
||||||
PageManager::Instance().release(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
// age=1 age=“hello”
|
// age=1 age=“hello”
|
||||||
void Collection::indexJSON(const std::string prefix, const nlohmann::json &json, const int& address) {
|
void Collection::indexJSON(const std::string prefix, const nlohmann::json &json, const int& address) {
|
||||||
// even easier with structured bindings (C++17)
|
// even easier with structured bindings (C++17)
|
||||||
@ -88,7 +14,7 @@ void Collection::indexJSON(const std::string prefix, const nlohmann::json &json,
|
|||||||
if(value.is_boolean()) insertIndex(prefix + key, value.get<bool>(), address);
|
if(value.is_boolean()) insertIndex(prefix + key, value.get<bool>(), address);
|
||||||
if(value.is_number()) insertIndex(prefix + key, value.get<double>(), address);
|
if(value.is_number()) insertIndex(prefix + key, value.get<double>(), address);
|
||||||
if(value.is_string()) insertIndex(prefix + key, value.get<std::string>(), address);
|
if(value.is_string()) insertIndex(prefix + key, value.get<std::string>(), address);
|
||||||
//if(value.is_object()) indexJSON(prefix + key + ".", value.get<nlohmann::json>(),address);
|
if(value.is_object()) indexJSON(prefix + key + ".", value.get<nlohmann::json>(),address);
|
||||||
if(value.is_array()) {
|
if(value.is_array()) {
|
||||||
for(auto& element : value.get<nlohmann::json>()) {
|
for(auto& element : value.get<nlohmann::json>()) {
|
||||||
if(element.is_string()) insertIndex(prefix + key, element.get<std::string>(), address);
|
if(element.is_string()) insertIndex(prefix + key, element.get<std::string>(), address);
|
||||||
@ -110,7 +36,7 @@ void Collection::insertIndex(const std::string indexName, const std::string inde
|
|||||||
index->insert(treeName, PageManager::Instance().allocate());
|
index->insert(treeName, PageManager::Instance().allocate());
|
||||||
}
|
}
|
||||||
|
|
||||||
BTree<std::string, 128> indexTree(index->find(treeName));
|
BTree<std::string, 64> indexTree(index->find(treeName));
|
||||||
|
|
||||||
if(!indexTree.exists(indexValue)) {
|
if(!indexTree.exists(indexValue)) {
|
||||||
indexTree.insert(indexValue, PageManager::Instance().allocate());
|
indexTree.insert(indexValue, PageManager::Instance().allocate());
|
||||||
@ -227,18 +153,4 @@ void Collection::removeIndex(const std::string indexName, bool indexValue, const
|
|||||||
|
|
||||||
List<int, 4> list(indexTree.find(indexValue));
|
List<int, 4> list(indexTree.find(indexValue));
|
||||||
list.remove(address);
|
list.remove(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Collection::test() {
|
|
||||||
index->print();
|
|
||||||
auto qq = new BTree<std::string, 128>(7);
|
|
||||||
while(true) {
|
|
||||||
std::string q;
|
|
||||||
std::cin >> q;
|
|
||||||
List<int, 4> list(qq->find(q));
|
|
||||||
//list.print();
|
|
||||||
for(auto& add : list.all()) {
|
|
||||||
std::cout << ">> " << PageManager::Instance().readJSONFromFile(add).dump() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
371
invodb/collection/query.cpp
Normal file
371
invodb/collection/query.cpp
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
//
|
||||||
|
// Created by projector-user on 11/1/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "collection.h"
|
||||||
|
|
||||||
|
std::vector<nlohmann::json> Collection::query(const nlohmann::json &json) {
|
||||||
|
std::vector<nlohmann::json> res;
|
||||||
|
|
||||||
|
innerQuery("", json);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* range search mod explain
|
||||||
|
* mod = 0: minValue <= value <= maxValue
|
||||||
|
* mod = 1: minValue < value <= maxValue
|
||||||
|
* mod = 2: minValue <= value < maxValue
|
||||||
|
* mod = 3: minValue < value < maxValue
|
||||||
|
* mod = 4: value < maxValue
|
||||||
|
* mod = 5: value <= maxValue
|
||||||
|
* mod = 6: value > minValue
|
||||||
|
* mod = 7: value >= minValue
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::set<nlohmann::json> Collection::queryRange(const std::string &prefix, const nlohmann::json &json) {
|
||||||
|
|
||||||
|
printf(">> queryRange prefix: %s query: %s\n", prefix.c_str(), json.dump().c_str());
|
||||||
|
|
||||||
|
std::set<nlohmann::json> set;
|
||||||
|
|
||||||
|
for(auto& [key, value] : json.items()) {
|
||||||
|
if(value.is_number()) {
|
||||||
|
|
||||||
|
if(json.contains("$ne")) {
|
||||||
|
if(!index->exists(prefix+"$number")) {
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
BTree<double, 8> tree(index->find(prefix+"$number"));
|
||||||
|
for(auto& key: tree.keySet()) {
|
||||||
|
if(key != json["$ne"].get<double>()) continue;
|
||||||
|
List<int, 4> list(tree.find(key));
|
||||||
|
for(auto& add : list.all()) {
|
||||||
|
set.insert(PageManager::Instance().readJSONFromFile(add));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(json.contains("$gt")) {
|
||||||
|
if(json.contains("$lt")) {
|
||||||
|
set = queryNumber(prefix, json["$gt"].get<double>(), json["$lt"].get<double>(), 3);
|
||||||
|
} else if(json.contains("$lte")) {
|
||||||
|
set = queryNumber(prefix, json["$gt"].get<double>(), json["$lte"].get<double>(), 1);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
set = queryNumber(prefix, json["$gt"].get<double>(), 0, 6);
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if(json.contains("$gte")) {
|
||||||
|
if(json.contains("$lt")) {
|
||||||
|
set = queryNumber(prefix, json["$gte"].get<double>(), json["$lt"].get<double>(), 2);
|
||||||
|
} else if(json.contains("$lte")) {
|
||||||
|
set = queryNumber(prefix, json["$gte"].get<double>(), json["$lte"].get<double>(), 0);
|
||||||
|
} else {
|
||||||
|
set = queryNumber(prefix, json["$gte"].get<double>(), 0, 7);
|
||||||
|
}
|
||||||
|
} else if(json.contains("$lt")) {
|
||||||
|
set = queryNumber(prefix, 0, json["$lt"].get<double>(), 4);
|
||||||
|
} else if(json.contains("$lte")) {
|
||||||
|
set = queryNumber(prefix, 0, json["$lte"].get<double>(), 5);
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
else if(value.is_string()) {
|
||||||
|
|
||||||
|
if(json.contains("$ne")) {
|
||||||
|
if(!index->exists(prefix+"$string")) {
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
BTree<std::string, 64> tree(index->find(prefix+"$string"));
|
||||||
|
for(auto& key: tree.keySet()) {
|
||||||
|
if(key != json["$ne"].get<std::string>()) continue;
|
||||||
|
List<int, 4> list(tree.find(key));
|
||||||
|
for(auto& add : list.all()) {
|
||||||
|
set.insert(PageManager::Instance().readJSONFromFile(add));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(json.contains("$gt")) {
|
||||||
|
if(json.contains("$lt")) {
|
||||||
|
set = queryString(prefix, json["$gt"].get<std::string>(), json["$lt"].get<std::string>(), 3);
|
||||||
|
} else if(json.contains("$lte")) {
|
||||||
|
set = queryString(prefix, json["$gt"].get<std::string>(), json["$lte"].get<std::string>(), 1);
|
||||||
|
} else {
|
||||||
|
set = queryString(prefix, json["$gt"].get<std::string>(), "", 6);
|
||||||
|
}
|
||||||
|
} else if(json.contains("$gte")) {
|
||||||
|
if(json.contains("$lt")) {
|
||||||
|
set = queryString(prefix, json["$gte"].get<std::string>(), json["$lt"].get<std::string>(), 2);
|
||||||
|
} else if(json.contains("$lte")) {
|
||||||
|
set = queryString(prefix, json["$gte"].get<std::string>(), json["$lte"].get<std::string>(), 0);
|
||||||
|
} else {
|
||||||
|
set = queryString(prefix, json["$gte"].get<std::string>(), "", 7);
|
||||||
|
}
|
||||||
|
} else if(json.contains("$lt")) {
|
||||||
|
set = queryString(prefix, "", json["$lt"].get<std::string>(), 4);
|
||||||
|
} else if(json.contains("$lte")) {
|
||||||
|
set = queryString(prefix, "", json["$lte"].get<std::string>(), 5);
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<nlohmann::json> Collection::innerQuery(const std::string &prefix, const nlohmann::json &json) {
|
||||||
|
|
||||||
|
for(auto& [key, value] : json.items()) {
|
||||||
|
if(key == "$lt" || key == "$lte" || key == "$gt" || key == "$gte" || key == "$ne") {
|
||||||
|
return queryRange(prefix.substr(0, prefix.size()-1), json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<nlohmann::json> res;
|
||||||
|
bool init = true;
|
||||||
|
|
||||||
|
for(auto& [key, value] : json.items()) {
|
||||||
|
|
||||||
|
std::set<nlohmann::json> tmp;
|
||||||
|
std::string tPrefix = prefix + key;
|
||||||
|
|
||||||
|
if(key == "$or") {
|
||||||
|
nlohmann::json line = json[key].get<nlohmann::json>();
|
||||||
|
for(auto& obj : line) {
|
||||||
|
tmp = setUnion(tmp, innerQuery(prefix, obj.get<nlohmann::json>()));
|
||||||
|
}
|
||||||
|
} else if(json[key].is_object()) {
|
||||||
|
tmp = innerQuery(prefix + key + ".", json[key].get<nlohmann::json>());
|
||||||
|
} else if(json[key].is_array()) {
|
||||||
|
|
||||||
|
} else if(json[key].is_boolean()) {
|
||||||
|
tmp = queryBool(tPrefix, json[key].get<bool>());
|
||||||
|
} else if(json[key].is_string()) {
|
||||||
|
tmp = queryString(tPrefix, json[key].get<std::string>(), json[key].get<std::string>());
|
||||||
|
} else if(json[key].is_number()) {
|
||||||
|
tmp = queryNumber(tPrefix, json[key].get<double>(), json[key].get<double>());
|
||||||
|
}
|
||||||
|
if(init) res = tmp, init = false;
|
||||||
|
else res = setIntersection(res, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto str = json.dump();
|
||||||
|
|
||||||
|
printf("query: %s prefix: %s\n", str.c_str(), prefix.c_str());
|
||||||
|
printf("result: \n");
|
||||||
|
for(auto it=res.begin(); it!=res.end(); it++) {
|
||||||
|
printf(" - %s\n", it->dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<nlohmann::json>
|
||||||
|
Collection::setIntersection(const std::set<nlohmann::json> &a, const std::set<nlohmann::json> &b) {
|
||||||
|
std::set<nlohmann::json> res;
|
||||||
|
std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::inserter(res, res.end()));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<nlohmann::json>
|
||||||
|
Collection::setUnion(const std::set<nlohmann::json> &a, const std::set<nlohmann::json> &b) {
|
||||||
|
std::set<nlohmann::json> res;
|
||||||
|
std::set_union(a.begin(), a.end(), b.begin(), b.end(), std::inserter(res, res.end()));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* range search mod explain
|
||||||
|
* mod = 0: minValue <= value <= maxValue
|
||||||
|
* mod = 1: minValue < value <= maxValue
|
||||||
|
* mod = 2: minValue <= value < maxValue
|
||||||
|
* mod = 3: minValue < value < maxValue
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::set<nlohmann::json>
|
||||||
|
Collection::queryString(const std::string &prefix, const std::string &minValue, const std::string &maxValue, const int &mod) {
|
||||||
|
std::set<nlohmann::json> res;
|
||||||
|
auto treeName = prefix + "$string";
|
||||||
|
//printf(">>>> %s %s %s\n", prefix.c_str(), minValue.c_str(), maxValue.c_str());
|
||||||
|
if(!index->exists(treeName)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
BTree<std::string, 64> tree(index->find(treeName));
|
||||||
|
const int K_SIZE = 64;
|
||||||
|
std::shared_ptr<BTreeNode<M_SIZE, std::string , K_SIZE>> node;
|
||||||
|
|
||||||
|
if(mod == 4 || mod == 5) {
|
||||||
|
node = tree.getNode(tree.findNode(maxValue));
|
||||||
|
} else {
|
||||||
|
node = tree.getNode(tree.findNode(minValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
bool flag = true;
|
||||||
|
for(int i=0; i<node->size; i++) {
|
||||||
|
if(mod == 0) {
|
||||||
|
if(node->keySet[i] < minValue) continue;
|
||||||
|
if(node->keySet[i] > maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 1) {
|
||||||
|
if(node->keySet[i] <= minValue) continue;
|
||||||
|
if(node->keySet[i] > maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 2) {
|
||||||
|
if(node->keySet[i] < minValue) continue;
|
||||||
|
if(node->keySet[i] >= maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 3) {
|
||||||
|
if(node->keySet[i] <= minValue) continue;
|
||||||
|
if(node->keySet[i] >= maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 4) {
|
||||||
|
if(node->keySet[i] >= maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 5) {
|
||||||
|
if(node->keySet[i] > maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 6) {
|
||||||
|
if(node->keySet[i] <= minValue) continue;
|
||||||
|
} else if(mod == 7) {
|
||||||
|
if(node->keySet[i] < minValue) continue;
|
||||||
|
}
|
||||||
|
List<int, 4> list(node->linkSet[i]);
|
||||||
|
for(auto& add : list.all()) {
|
||||||
|
res.insert(PageManager::Instance().readJSONFromFile(add));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!flag) break;
|
||||||
|
if(node->right == 0) break;
|
||||||
|
node = tree.getNode(node->right);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* range search mod explain
|
||||||
|
* mod = 0: minValue <= value <= maxValue
|
||||||
|
* mod = 1: minValue < value <= maxValue
|
||||||
|
* mod = 2: minValue <= value < maxValue
|
||||||
|
* mod = 3: minValue < value < maxValue
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::set<nlohmann::json>
|
||||||
|
Collection::queryNumber(const std::string &prefix, const double &minValue, const double &maxValue, const int &mod) {
|
||||||
|
std::set<nlohmann::json> res;
|
||||||
|
auto treeName = prefix + "$number";
|
||||||
|
printf(">>>> %s %f %f\n", prefix.c_str(), minValue, maxValue);
|
||||||
|
|
||||||
|
if(!index->exists(treeName)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
BTree<double, 8> tree(index->find(treeName));
|
||||||
|
const int K_SIZE = 8;
|
||||||
|
std::shared_ptr<BTreeNode<M_SIZE, double , K_SIZE>> node;
|
||||||
|
|
||||||
|
if(mod == 4 || mod == 5) {
|
||||||
|
node = tree.getNode(tree.findNode(maxValue));
|
||||||
|
} else {
|
||||||
|
node = tree.getNode(tree.findNode(minValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
bool flag = true;
|
||||||
|
for(int i=0; i<node->size; i++) {
|
||||||
|
|
||||||
|
if(mod == 0) {
|
||||||
|
if(node->keySet[i] < minValue) continue;
|
||||||
|
if(node->keySet[i] > maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 1) {
|
||||||
|
if(node->keySet[i] <= minValue) continue;
|
||||||
|
if(node->keySet[i] > maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 2) {
|
||||||
|
if(node->keySet[i] < minValue) continue;
|
||||||
|
if(node->keySet[i] >= maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 3) {
|
||||||
|
if(node->keySet[i] <= minValue) continue;
|
||||||
|
if(node->keySet[i] >= maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 4) {
|
||||||
|
if(node->keySet[i] >= maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 5) {
|
||||||
|
if(node->keySet[i] > maxValue) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(mod == 6) {
|
||||||
|
if(node->keySet[i] <= minValue) continue;
|
||||||
|
} else if(mod == 7) {
|
||||||
|
if(node->keySet[i] < minValue) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
List<int, 4> list(node->linkSet[i]);
|
||||||
|
for(auto& add : list.all()) {
|
||||||
|
res.insert(PageManager::Instance().readJSONFromFile(add));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!flag) break;
|
||||||
|
if(node->right == 0) break;
|
||||||
|
node = tree.getNode(node->right);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<nlohmann::json>
|
||||||
|
Collection::queryBool(const std::string &prefix, const bool &value) {
|
||||||
|
std::set<nlohmann::json> res;
|
||||||
|
auto treeName = prefix + "$boolean";
|
||||||
|
//printf(">>>> %s %s %s\n", prefix.c_str(), minValue.c_str(), maxValue.c_str());
|
||||||
|
if(!index->exists(treeName)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
BTree<bool, 1> tree(index->find(treeName));
|
||||||
|
auto node = tree.getNode(tree.findNode(value));
|
||||||
|
while(true) {
|
||||||
|
bool flag = true;
|
||||||
|
for(int i=0; i<node->size; i++) {
|
||||||
|
if(node->keySet[i] < value) continue;
|
||||||
|
if(node->keySet[i] > value) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
List<int, 4> list(node->linkSet[i]);
|
||||||
|
for(auto& add : list.all()) {
|
||||||
|
res.insert(PageManager::Instance().readJSONFromFile(add));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!flag) break;
|
||||||
|
if(node->right == 0) break;
|
||||||
|
node = tree.getNode(node->right);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include "storage_page.h"
|
#include "storage_page.h"
|
||||||
#include "json/json.hpp"
|
#include "json/json.hpp"
|
||||||
#include "invodb/models/cache.h"
|
#include "invodb/utils/cache.h"
|
||||||
|
|
||||||
template<typename T, int T_SIZE>
|
template<typename T, int T_SIZE>
|
||||||
class List;
|
class List;
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by YuhangQ on 2021/11/1.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "index.h"
|
|
@ -1,25 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by YuhangQ on 2021/11/1.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef INVODB_INDEX_H
|
|
||||||
#define INVODB_INDEX_H
|
|
||||||
|
|
||||||
#include "btree/btree.h"
|
|
||||||
#include "json/json.hpp"
|
|
||||||
|
|
||||||
class Index {
|
|
||||||
public:
|
|
||||||
void insert(const nlohmann::json& json);
|
|
||||||
private:
|
|
||||||
template<typename T>
|
|
||||||
void insertElement(T const& key, const int& add) {
|
|
||||||
BTree<T, 128> treeString;
|
|
||||||
BTree<T, 1> treeBool;
|
|
||||||
BTree<T, 8> treeDouble;
|
|
||||||
BTree<T, 4> treeInt;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //INVODB_INDEX_H
|
|
@ -1,9 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by projector-user on 11/1/21.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "query.h"
|
|
||||||
|
|
||||||
std::vector<nlohmann::json> Query::find(const nlohmann::json &json) {
|
|
||||||
return std::vector<nlohmann::json>();
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by projector-user on 11/1/21.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef INVODB_QUERY_H
|
|
||||||
#define INVODB_QUERY_H
|
|
||||||
|
|
||||||
#include "json/json.hpp"
|
|
||||||
|
|
||||||
class Query {
|
|
||||||
std::vector<nlohmann::json> find(const nlohmann::json &json);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //INVODB_QUERY_H
|
|
@ -29,42 +29,58 @@ int main() {
|
|||||||
col = &Collection::getCollection("hello");
|
col = &Collection::getCollection("hello");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nlohmann::json j = nlohmann::json::parse(R"(
|
||||||
|
{
|
||||||
|
"title" : "MongoDB 教程",
|
||||||
|
"description" : "MongoDB 是一个 Nosql 数据库",
|
||||||
|
"by" : "菜鸟教程",
|
||||||
|
"url" : "http://www.runoob.com",
|
||||||
|
"tags" : [
|
||||||
|
"mongodb",
|
||||||
|
"database",
|
||||||
|
"NoSQL"
|
||||||
|
],
|
||||||
|
"likes" : 100
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
|
||||||
freopen("qq.txt", "r", stdin);
|
col->insert(j);
|
||||||
const int n = 1000000;
|
|
||||||
char qq[100], phone[100];
|
|
||||||
|
|
||||||
clock_t start = clock();
|
col->query(nlohmann::json::parse(R"(
|
||||||
for(int i=0; i<n; i++) {
|
{
|
||||||
scanf("%s%s", qq, phone);
|
"likes": {"$gt":50},
|
||||||
nlohmann::json json;
|
"$or": [
|
||||||
json["qq"] = qq;
|
{"by": "菜鸟教程"},
|
||||||
json["phone"] = phone;
|
{"title": "MongoDB 教程"}
|
||||||
col->insert(json);
|
]
|
||||||
|
}
|
||||||
|
)"));
|
||||||
|
|
||||||
if(i % (n/1000) == 0) {
|
|
||||||
printf("[%d/%d] time=%fs!\n", i, n, (double)(clock() - start) / CLOCKS_PER_SEC);
|
// freopen("qq.txt", "r", stdin);
|
||||||
start = clock();
|
// const int n = 1000000;
|
||||||
}
|
// char qq[100], phone[100];
|
||||||
}
|
//
|
||||||
|
// clock_t start = clock();
|
||||||
|
// for(int i=0; i<n; i++) {
|
||||||
|
// scanf("%s%s", qq, phone);
|
||||||
|
// nlohmann::json json;
|
||||||
|
// json["qq"] = qq;
|
||||||
|
// json["phone"] = phone;
|
||||||
|
// col->insert(json);
|
||||||
|
//
|
||||||
|
// if(i % (n/1000) == 0) {
|
||||||
|
// printf("[%d/%d] time=%fs!\n", i, n, (double)(clock() - start) / CLOCKS_PER_SEC);
|
||||||
|
// start = clock();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
//col->test();
|
//col->test();
|
||||||
|
|
||||||
|
|
||||||
// nlohmann::json j = nlohmann::json::parse(R"(
|
|
||||||
//{
|
|
||||||
// "string": "this is a string!",
|
|
||||||
// "double": 3.1415,
|
|
||||||
// "int": 25565,
|
|
||||||
// "bool": true,
|
|
||||||
// "child": {
|
|
||||||
// "id": 3
|
|
||||||
// },
|
|
||||||
// "array": ["1", "2", "3"]
|
|
||||||
//}
|
|
||||||
// )");
|
|
||||||
|
|
||||||
testAndBenchmark(20000);
|
|
||||||
|
//testAndBenchmark(20000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "models/collection.h"
|
#include "collection/collection.h"
|
||||||
#include "btree/list.h"
|
#include "btree/list.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -11442,11 +11442,11 @@ namespace detail
|
|||||||
/*
|
/*
|
||||||
@brief an iterator for primitive JSON types
|
@brief an iterator for primitive JSON types
|
||||||
|
|
||||||
This class models an iterator for primitive JSON types (boolean, number,
|
This class collection an iterator for primitive JSON types (boolean, number,
|
||||||
string). It's only purpose is to allow the iterator/const_iterator classes
|
string). It's only purpose is to allow the iterator/const_iterator classes
|
||||||
to "iterate" over primitive values. Internally, the iterator is modeled by
|
to "iterate" over primitive values. Internally, the iterator is modeled by
|
||||||
a `difference_type` variable. Value begin_value (`0`) models the begin,
|
a `difference_type` variable. Value begin_value (`0`) collection the begin,
|
||||||
end_value (`1`) models past the end.
|
end_value (`1`) collection past the end.
|
||||||
*/
|
*/
|
||||||
class primitive_iterator_t
|
class primitive_iterator_t
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user