diff --git a/binding.gyp b/binding.gyp index 43fd267..d7c37f5 100644 --- a/binding.gyp +++ b/binding.gyp @@ -21,7 +21,12 @@ "defines": ["NAPI_CPP_EXCEPTIONS"], "xcode_settings": { "GCC_ENABLE_CPP_EXCEPTIONS": "YES" - } + }, + 'msvs_settings': { + 'VCCLCompilerTool': { + 'AdditionalOptions': [ '-std:c++17', ], + }, + }, } ] } \ No newline at end of file diff --git a/demo/test.js b/demo/test.js index 8d091e7..19e6686 100644 --- a/demo/test.js +++ b/demo/test.js @@ -5,17 +5,18 @@ invodb.database('zzz.invodb') let col = invodb.colection('blog') if(!col.exist()) col.create(); -col.insert({ id: 1, title: "第一篇文章", author: "YuhangQ"}) -col.insert({ id: 2, title: "第二篇文章", author: "Ciel"}) -col.insert({ id: 3, title: "第三篇文章", author: "YuhangQ"}) -col.insert({ id: 4, title: "第四篇文章", author: "By"}) +for(let i=0; i<1; i++) { + col.insert({ id: "1s", title: "第一篇文章", author: "YuhangQ"}) + col.insert({ id: "2s", title: "第二篇文章", author: "Ciel"}) + col.insert({ id: "3s", title: "第三篇文章", author: "YuhangQ"}) + col.insert({ id: "4s", title: "第四篇文章", author: "By"}) +} -let result = col.query({ - id: { - $gte: 2, - $lte: 3 - }, - author: "YuhangQ" -}) +let result = col.query({id: {}}) -console.log(result) \ No newline at end of file +// for(let json of result) { +// col.remove(json) +// } + +console.log(result) +console.log(result.length) \ No newline at end of file diff --git a/index.js b/index.js index 8d7089f..6ac181a 100644 --- a/index.js +++ b/index.js @@ -20,7 +20,11 @@ function colection(collectionName) { function query(object) { if(!core.exists(collectionName)) throw `Collection ${collectionName} doesn't exists!`; let json = JSON.stringify(object); - return core.query(collectionName, json); + let res = []; + for(let str of core.query(collectionName, json)) { + res.push(JSON.parse(str)); + } + return res; } return { exist: exist, diff --git a/package.json b/package.json index f378c54..a534f4c 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "a nosql json document database", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "clear && node-gyp build && node demo/test.js", "install": "node-gyp rebuild" }, "repository": { diff --git a/src/collection/collection.cpp b/src/collection/collection.cpp index d967b03..3049e0a 100644 --- a/src/collection/collection.cpp +++ b/src/collection/collection.cpp @@ -59,7 +59,7 @@ void Collection::insert(nlohmann::json &json) { int add = PageManager::Instance().saveJSONToFile(json); uuid->insert(id, add); - Logger::info("INSERT ", json.dump()); + //Logger::info("INSERT ", json.dump()); // add index indexJSON("", json, add); diff --git a/src/collection/collection.h b/src/collection/collection.h index 1599000..c45e12e 100644 --- a/src/collection/collection.h +++ b/src/collection/collection.h @@ -29,6 +29,8 @@ public: void test(); private: + + 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, double indexValue, const int& address); @@ -41,11 +43,13 @@ private: std::set setIntersection(const std::set &a, const std::set &b); std::set setUnion(const std::set &a, const std::set &b); + std::set innerQuery(const std::string &prefix, const nlohmann::json &json); std::set queryString(const std::string &prefix, const std::string &minValue, const std::string &maxValue, const int &mod = 0); std::set queryNumber(const std::string &prefix, const double &minValue, const double &maxValue, const int &mod = 0); std::set queryBool(const std::string &prefix, const bool &value); std::set queryRange(const std::string &prefix, const nlohmann::json &json); + std::set queryAllByField(const std::string &fieldName); static std::map map; static BTree colList; diff --git a/src/collection/query.cpp b/src/collection/query.cpp index 4c8a9ff..64f4724 100644 --- a/src/collection/query.cpp +++ b/src/collection/query.cpp @@ -26,13 +26,12 @@ std::vector Collection::query(const nlohmann::json &json) { std::set Collection::queryRange(const std::string &prefix, const nlohmann::json &json) { - //printf(">> queryRange prefix: %s query: %s\n", prefix.c_str(), json.dump().c_str()); + printf(">> queryRange prefix: %s query: %s\n", prefix.c_str(), json.dump().c_str()); std::set set; for(auto& [key, value] : json.items()) { if(value.is_number()) { - if(json.contains("$ne")) { if(!index->exists(prefix+"$number")) { return set; @@ -113,7 +112,6 @@ std::set Collection::queryRange(const std::string &prefix, const return set; } - std::set Collection::innerQuery(const std::string &prefix, const nlohmann::json &json) { for(auto& [key, value] : json.items()) { @@ -123,7 +121,7 @@ std::set Collection::innerQuery(const std::string &prefix, const } std::set res; - bool init = true; + bool init = true, flag = false; for(auto& [key, value] : json.items()) { @@ -138,7 +136,34 @@ std::set Collection::innerQuery(const std::string &prefix, const } else if(json[key].is_object()) { tmp = innerQuery(prefix + key + ".", json[key].get()); } else if(json[key].is_array()) { - + flag = true; + for(auto element : json[key].get()) { + if(element.is_boolean()) { + if (flag) + { + tmp = queryBool(tPrefix, element.get()); + flag = false; + } + else + tmp = setIntersection(queryBool(tPrefix, element.get()), tmp); + } else if(element.is_string()) { + if (flag) + { + tmp = queryString(tPrefix, element.get(), element.get()); + flag = false; + } + else + tmp = setIntersection(queryString(tPrefix, element.get(), element.get()), tmp); + } else if(element.is_number()) { + if (flag) + { + tmp = queryNumber(tPrefix, element.get(), element.get()); + flag = false; + } + else + tmp = setIntersection(queryNumber(tPrefix, element.get(), element.get()), tmp); + } + } } else if(json[key].is_boolean()) { tmp = queryBool(tPrefix, json[key].get()); } else if(json[key].is_string()) { @@ -146,18 +171,71 @@ std::set Collection::innerQuery(const std::string &prefix, const } else if(json[key].is_number()) { tmp = queryNumber(tPrefix, json[key].get(), json[key].get()); } + if (flag) continue; 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()); + } - // 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()); - // } + if (init) return queryAllByField(prefix); + + + + return res; +} + + + +std::set Collection::queryAllByField(const std::string &fieldName) { + std::set res; + + // return all + if(fieldName == "") { + for(auto& [key, value] : uuid->all()) { + res.insert(PageManager::Instance().readJSONFromFile(value)); + } + } else { + auto tfieldName = fieldName.substr(0, fieldName.size()-1); + + int treeID; + + if((treeID = index->find(tfieldName + "$string")) != -1) { + BTree tree(treeID); + for(auto &[key, value] : tree.all()) { + List list(value); + for(auto& add : list.all()) { + res.insert(PageManager::Instance().readJSONFromFile(add)); + } + } + } + + if((treeID = index->find(tfieldName + "$number")) != -1) { + BTree tree(treeID); + for(auto &[key, value] : tree.all()) { + List list(value); + for(auto& add : list.all()) { + res.insert(PageManager::Instance().readJSONFromFile(add)); + } + } + } + + if((treeID = index->find(tfieldName + "$boolean")) != -1) { + BTree tree(treeID); + for(auto &[key, value] : tree.all()) { + List list(value); + for(auto& add : list.all()) { + res.insert(PageManager::Instance().readJSONFromFile(add)); + } + } + } + } return res; } @@ -267,7 +345,7 @@ std::set Collection::queryNumber(const std::string &prefix, const double &minValue, const double &maxValue, const int &mod) { std::set res; auto treeName = prefix + "$number"; - //printf(">>>> %s %f %f\n", prefix.c_str(), minValue, maxValue); + printf(">>>> %s %f %f %d\n", prefix.c_str(), minValue, maxValue, mod); if(!index->exists(treeName)) { return res; diff --git a/src/file/page_manager.cpp b/src/file/page_manager.cpp index 45f0ddd..50d1105 100644 --- a/src/file/page_manager.cpp +++ b/src/file/page_manager.cpp @@ -5,10 +5,14 @@ #include "page_manager.h" int PageManager::loadDatabase(const char *filename) { - std::ofstream file(filename, std::fstream::out); - file.close(); Instance().stream.open(filename); Instance().stream.seekp(0, std::ios::end); + if(!Instance().stream.is_open()) { + std::ofstream file(filename, std::fstream::out); + file.close(); + Instance().stream.open(filename); + Instance().stream.seekp(0, std::ios::end); + } int index = Instance().stream.tellp() / 1024; if(index == 0) { StoragePage page(0); diff --git a/src/utils/uuid.h b/src/utils/uuid.h index 9a7a7ac..fcb1c8e 100644 --- a/src/utils/uuid.h +++ b/src/utils/uuid.h @@ -17,25 +17,4 @@ inline std::string generateUUID() { return std::string(uuid, 32); } -inline std::string appropriateString(const std::string& s, const int& offset) { - int a[s.size()]; - for(int i=0; i=0; i--) { - res += a[i]; - } - return res; -} - #endif //INVODB_UUID_H diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..65ee546 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +node-addon-api@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.2.0.tgz#117cbb5a959dff0992e1c586ae0393573e4d2a87" + integrity sha512-eazsqzwG2lskuzBqCGPi7Ac2UgOoMz8JVOXVhTvvPDYhthvNpefx8jWD8Np7Gv+2Sz0FlPWZk0nJV0z598Wn8Q==