datafolder 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/index.js +2 -3
- package/package.json +3 -2
- package/sample.js +37 -37
- package/scripts/airbnb.js +10 -11
- package/scripts/airbnb2.js +10 -11
- package/scripts/airbnb2_queries.js +11 -11
- package/scripts/airbnb_queries.js +15 -14
- package/scripts/downloadFile.js +29 -31
- package/scripts/express.js +5 -4
- package/scripts/fastify.js +12 -11
- package/scripts/flights.js +8 -8
- package/scripts/flights2.js +9 -9
- package/scripts/flights2_queries.js +19 -16
- package/scripts/flights_queries.js +18 -13
- package/src/QyAcl.js +153 -152
- package/src/QyAclSaver.js +16 -10
- package/src/QyAclSaver_Worker.js +21 -15
- package/src/QyAclWriter.js +23 -13
- package/src/QyBatch.js +298 -263
- package/src/QyBinWriter.js +49 -37
- package/src/QyCD.js +13 -14
- package/src/QyCache.js +177 -140
- package/src/QyCompressor.js +71 -45
- package/src/QyCompressor_Worker.js +17 -9
- package/src/QyDB.js +41 -12
- package/src/QyDefaultOptions.js +13 -10
- package/src/QyDir.js +89 -53
- package/src/QyFetch.js +27 -24
- package/src/QyFile.js +89 -77
- package/src/QyFileContentUtils.js +129 -132
- package/src/QyFileLogger.js +63 -41
- package/src/QyIndex.js +175 -197
- package/src/QyIndexPropTree.js +25 -25
- package/src/QyIntersectNode.js +34 -31
- package/src/QyItem.js +54 -52
- package/src/QyJsonSaver.js +12 -6
- package/src/QyKVData.js +279 -245
- package/src/QyKVDataCleaner.js +12 -6
- package/src/QyKVDataCleaner_Worker.js +77 -59
- package/src/QyKVDataLoader.js +67 -46
- package/src/QyKVDataSaver.js +15 -9
- package/src/QyKVDataSaver_Worker.js +83 -60
- package/src/QyLogFileSaver.js +12 -6
- package/src/QyLogFileSaver_Worker.js +24 -14
- package/src/QyLogger.js +51 -40
- package/src/QyMessageWorker.js +43 -29
- package/src/QyMessager.js +74 -54
- package/src/QyMessager_Run.js +20 -7
- package/src/QyMod.js +15 -11
- package/src/QyOpRunner.js +58 -41
- package/src/QyQueue.js +35 -30
- package/src/QySaver.js +52 -29
- package/src/QySnapshotCompactor.js +15 -9
- package/src/QySnapshotCompactor_Worker.js +131 -110
- package/src/QySnapshotSaver.js +15 -9
- package/src/QySnapshotSaver_Worker.js +125 -110
- package/src/QySnapshots.js +260 -241
- package/src/QyStructure.js +35 -27
- package/src/QyTrigger.js +62 -55
- package/src/QyUnionNode.js +54 -56
- package/src/QyUtils.js +170 -158
- package/src/QyWorker.js +34 -20
- package/src/hackernews.js +63 -71
- package/src/rpc/getFileContent.js +7 -7
- package/src/rpc/getSubItems.js +22 -22
- package/src/simulate.js +85 -80
- package/src/simulate2.js +77 -78
- package/src/soc_pokec.js +44 -32
- package/static/datafolderui/QyStyledElement.js +12 -12
- package/static/datafolderui/QyUIFolderTree.js +20 -20
- package/static/datafolderui/QyUIUtils.js +8 -8
- package/static/datafolderui/explore-tree.js +31 -31
- package/static/datafolderui/folder-tree.js +2 -2
- package/static/datafolderui/hscrpt.js +9 -17
- package/static/datafolderui/json-view.js +3 -5
- package/static/datafolderui/kv-input.js +15 -15
- package/static/datafolderui/list-input.js +17 -17
- package/static/datafolderui/main-page.js +18 -18
- package/static/datafolderui/num-input.js +5 -5
- package/static/datafolderui/querySelectorShadowRoot.js +15 -19
- package/static/datafolderui/resizable-input.js +18 -18
package/README.md
CHANGED
|
@@ -11,9 +11,9 @@ datafolder is a lightweight JSON database, featuring an AI-friendly API for simp
|
|
|
11
11
|
## How to use
|
|
12
12
|
|
|
13
13
|
```javascript
|
|
14
|
-
|
|
14
|
+
import DataFolder from "datafolder";
|
|
15
15
|
const dataFolder = new DataFolder(); //Specify where to store the data. Default is ./data/sampleDataFolder
|
|
16
|
-
await dataFolder.start();
|
|
16
|
+
await dataFolder.start(); //start() and stop() are the only two async places. All other code doesn't need await.
|
|
17
17
|
dataFolder.insert("users/2026/user_0001", {
|
|
18
18
|
userid: "user_0001",
|
|
19
19
|
email: "a@b.com",
|
|
@@ -107,7 +107,13 @@ dataFolder.batch
|
|
|
107
107
|
|
|
108
108
|
```javascript
|
|
109
109
|
dataFolder.queryFiles("flights/**", { _from: "airports/LAX" });
|
|
110
|
-
dataFolder.queryFiles(["flights", "*",
|
|
110
|
+
dataFolder.queryFiles(["flights", "*", "jan", (x) => x >= 5 && x <= 7], {
|
|
111
|
+
$or: [{ _from: "airports/BIS" }, { _to: "airports/BIS" }],
|
|
112
|
+
});
|
|
113
|
+
dataFolder.queryFiles(["flights", "*", "feb", { $or: [5, 6, 7] }], {
|
|
114
|
+
$or: [{ _from: "airports/BIS" }, { _to: "airports/BIS" }],
|
|
115
|
+
});
|
|
116
|
+
dataFolder.queryFiles(["flights", "*", "mar", { $gte: 5, lte: 7 }], {
|
|
111
117
|
$or: [{ _from: "airports/BIS" }, { _to: "airports/BIS" }],
|
|
112
118
|
});
|
|
113
119
|
dataFolder.queryFilesMulti([
|
package/index.js
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
module.exports.default = QyDB;
|
|
1
|
+
import { QyDB } from "./src/QyDB.js";
|
|
2
|
+
export default QyDB;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "datafolder",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "lysh",
|
|
6
6
|
"email": "datafolderdev@outlook.com"
|
|
@@ -50,5 +50,6 @@
|
|
|
50
50
|
"scripts": {
|
|
51
51
|
"ui": "start http://localhost:3628/datafolderui/index.html && node ./scripts/fastify.js",
|
|
52
52
|
"airbnb": "node ./scripts/airbnb2.js && start http://localhost:3628/datafolderui/index.html && node ./scripts/fastify.js"
|
|
53
|
-
}
|
|
53
|
+
},
|
|
54
|
+
"type": "module"
|
|
54
55
|
}
|
package/sample.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
const dataFolder = new DataFolder();
|
|
3
|
-
|
|
4
|
-
run();
|
|
5
|
-
|
|
6
|
-
async function run() {
|
|
7
|
-
await dataFolder.start();
|
|
8
|
-
dataFolder.insert("users/2026/user_0001", {
|
|
9
|
-
userid: "user_0001",
|
|
10
|
-
email: "a@b.com",
|
|
11
|
-
password: "123",
|
|
12
|
-
score: 5,
|
|
13
|
-
address: { city: "a", zipcode: 123 },
|
|
14
|
-
});
|
|
15
|
-
dataFolder.insert("users/2026/user_0002", {
|
|
16
|
-
userid: "user_0002",
|
|
17
|
-
email: "c@b.com",
|
|
18
|
-
password: "333",
|
|
19
|
-
score: 3,
|
|
20
|
-
address: { city: "b", zipcode: 321 },
|
|
21
|
-
});
|
|
22
|
-
const { email, password, address, score } = dataFolder.view("users/2026/user_0002");
|
|
23
|
-
logger.log(email, password, score, address);
|
|
24
|
-
address.zipcode = 678;
|
|
25
|
-
dataFolder.insert("users/2026/user_0002", { score: score + 1, address });
|
|
26
|
-
logger.log(dataFolder.view("users/2026/user_0002", ["score", "address"]));
|
|
27
|
-
await dataFolder.stop();
|
|
28
|
-
await dataFolder.start();
|
|
29
|
-
{
|
|
30
|
-
const file = dataFolder.file("users/2026/user_0002");
|
|
31
|
-
const { email, password, score } = file.view();
|
|
32
|
-
logger.log(email, password, score);
|
|
33
|
-
dataFolder.insert(file, { score: score + 1 });
|
|
34
|
-
logger.log(file.view());
|
|
35
|
-
}
|
|
36
|
-
await dataFolder.stop();
|
|
37
|
-
}
|
|
1
|
+
import DataFolder from "datafolder";
|
|
2
|
+
const dataFolder = new DataFolder();
|
|
3
|
+
|
|
4
|
+
run();
|
|
5
|
+
|
|
6
|
+
async function run() {
|
|
7
|
+
await dataFolder.start();
|
|
8
|
+
dataFolder.insert("users/2026/user_0001", {
|
|
9
|
+
userid: "user_0001",
|
|
10
|
+
email: "a@b.com",
|
|
11
|
+
password: "123",
|
|
12
|
+
score: 5,
|
|
13
|
+
address: { city: "a", zipcode: 123 },
|
|
14
|
+
});
|
|
15
|
+
dataFolder.insert("users/2026/user_0002", {
|
|
16
|
+
userid: "user_0002",
|
|
17
|
+
email: "c@b.com",
|
|
18
|
+
password: "333",
|
|
19
|
+
score: 3,
|
|
20
|
+
address: { city: "b", zipcode: 321 },
|
|
21
|
+
});
|
|
22
|
+
const { email, password, address, score } = dataFolder.view("users/2026/user_0002");
|
|
23
|
+
logger.log(email, password, score, address);
|
|
24
|
+
address.zipcode = 678;
|
|
25
|
+
dataFolder.insert("users/2026/user_0002", { score: score + 1, address });
|
|
26
|
+
logger.log(dataFolder.view("users/2026/user_0002", ["score", "address"]));
|
|
27
|
+
await dataFolder.stop();
|
|
28
|
+
await dataFolder.start();
|
|
29
|
+
{
|
|
30
|
+
const file = dataFolder.file("users/2026/user_0002");
|
|
31
|
+
const { email, password, score } = file.view();
|
|
32
|
+
logger.log(email, password, score);
|
|
33
|
+
dataFolder.insert(file, { score: score + 1 });
|
|
34
|
+
logger.log(file.view());
|
|
35
|
+
}
|
|
36
|
+
await dataFolder.stop();
|
|
37
|
+
}
|
package/scripts/airbnb.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { open, rm } from "node:fs/promises";
|
|
3
|
+
import { QyDB } from "../src/QyDB.js";
|
|
4
|
+
import { folderOrFileExists, isSimpleType, __dirname } from "../src/QyUtils.js";
|
|
5
|
+
import { runQueries } from "./airbnb_queries.js";
|
|
6
|
+
import { downloadFile } from "./downloadFile.js";
|
|
7
7
|
|
|
8
8
|
const fileName = "listingsAndReviews.json";
|
|
9
9
|
const fileUrl = `https://raw.githubusercontent.com/neelabalan/mongodb-sample-dataset/refs/heads/main/sample_airbnb/${fileName}`;
|
|
10
|
-
const airbnbJsonFilePath =
|
|
10
|
+
const airbnbJsonFilePath = join(__dirname, "../data/", fileName);
|
|
11
11
|
const qyDB = new QyDB();
|
|
12
12
|
const { rootFolder } = qyDB;
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ run();
|
|
|
15
15
|
async function insertData() {
|
|
16
16
|
console.time("insertData");
|
|
17
17
|
const { batch } = qyDB;
|
|
18
|
-
const fileHandle = await
|
|
18
|
+
const fileHandle = await open(airbnbJsonFilePath, "r");
|
|
19
19
|
for await (const line of fileHandle.readLines()) {
|
|
20
20
|
const oneItem = convert(JSON.parse(line));
|
|
21
21
|
batch.insert(["airbnb1", oneItem._id], oneItem);
|
|
@@ -39,7 +39,7 @@ async function run() {
|
|
|
39
39
|
let shouldInsertData = true;
|
|
40
40
|
if (process.argv[2] == "true") {
|
|
41
41
|
try {
|
|
42
|
-
await
|
|
42
|
+
await rm(rootFolder, { recursive: true });
|
|
43
43
|
} catch (exception) {}
|
|
44
44
|
shouldInsertData = true;
|
|
45
45
|
} else if (!(await folderOrFileExists(rootFolder))) shouldInsertData = true;
|
|
@@ -69,5 +69,4 @@ function convert(item) {
|
|
|
69
69
|
item[prop] = convert(item[prop]);
|
|
70
70
|
}
|
|
71
71
|
return item;
|
|
72
|
-
}
|
|
73
|
-
Object.assign(module.exports, { runQueries });
|
|
72
|
+
}
|
package/scripts/airbnb2.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { open, rm } from "node:fs/promises";
|
|
3
|
+
import { QyDB } from "../src/QyDB.js";
|
|
4
|
+
import { folderOrFileExists, isSimpleType, __dirname } from "../src/QyUtils.js";
|
|
5
|
+
import { runQueries } from "./airbnb2_queries.js";
|
|
6
|
+
import { downloadFile } from "./downloadFile.js";
|
|
7
7
|
|
|
8
8
|
const fileName = "listingsAndReviews.json";
|
|
9
9
|
const fileUrl = `https://raw.githubusercontent.com/neelabalan/mongodb-sample-dataset/refs/heads/main/sample_airbnb/${fileName}`;
|
|
10
|
-
const airbnbJsonFilePath =
|
|
10
|
+
const airbnbJsonFilePath = join(__dirname, "../data/", fileName);
|
|
11
11
|
const qyDB = new QyDB();
|
|
12
12
|
const { rootFolder } = qyDB;
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ run();
|
|
|
15
15
|
async function insertData() {
|
|
16
16
|
console.time("insertData");
|
|
17
17
|
const { batch } = qyDB;
|
|
18
|
-
const fileHandle = await
|
|
18
|
+
const fileHandle = await open(airbnbJsonFilePath, "r");
|
|
19
19
|
for await (const line of fileHandle.readLines()) {
|
|
20
20
|
const oneItem = convert(JSON.parse(line));
|
|
21
21
|
const { property_type, room_type, bed_type, _id } = oneItem;
|
|
@@ -40,7 +40,7 @@ async function run() {
|
|
|
40
40
|
let shouldInsertData = true;
|
|
41
41
|
if (process.argv[2] == "true") {
|
|
42
42
|
try {
|
|
43
|
-
await
|
|
43
|
+
await rm(rootFolder, { recursive: true });
|
|
44
44
|
} catch (exception) {}
|
|
45
45
|
shouldInsertData = true;
|
|
46
46
|
} else if (!(await folderOrFileExists(rootFolder))) shouldInsertData = true;
|
|
@@ -70,5 +70,4 @@ function convert(item) {
|
|
|
70
70
|
item[prop] = convert(item[prop]);
|
|
71
71
|
}
|
|
72
72
|
return item;
|
|
73
|
-
}
|
|
74
|
-
Object.assign(module.exports, { runQueries });
|
|
73
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { deepEqual } from "node:assert/strict";
|
|
2
2
|
|
|
3
3
|
function query1(qyDB) {
|
|
4
4
|
console.time("query1");
|
|
5
|
-
|
|
5
|
+
deepEqual(
|
|
6
6
|
qyDB
|
|
7
7
|
.queryFiles(["airbnb", "Loft", "Entire home/apt", "Real Bed"], {
|
|
8
8
|
address: { street: "Porto, Porto, Portugal" },
|
|
@@ -32,7 +32,7 @@ function query1(qyDB) {
|
|
|
32
32
|
}
|
|
33
33
|
function query2(qyDB) {
|
|
34
34
|
console.time("query2");
|
|
35
|
-
|
|
35
|
+
deepEqual(
|
|
36
36
|
qyDB
|
|
37
37
|
.queryFiles(
|
|
38
38
|
["airbnb", "Loft", "Entire home/apt", "Real Bed"],
|
|
@@ -58,7 +58,7 @@ function query2(qyDB) {
|
|
|
58
58
|
}
|
|
59
59
|
function query3(qyDB) {
|
|
60
60
|
console.time("query3");
|
|
61
|
-
|
|
61
|
+
deepEqual(
|
|
62
62
|
qyDB
|
|
63
63
|
.queryFiles(
|
|
64
64
|
["airbnb", "Loft", "Entire home/apt", "Real Bed"],
|
|
@@ -82,7 +82,7 @@ function query3(qyDB) {
|
|
|
82
82
|
}
|
|
83
83
|
function query4(qyDB) {
|
|
84
84
|
console.time("query4");
|
|
85
|
-
|
|
85
|
+
deepEqual(
|
|
86
86
|
qyDB.fetch
|
|
87
87
|
.queryFilesMulti([
|
|
88
88
|
[["airbnb", "Loft", "Entire home/apt", "Real Bed"], { address: { street: "Porto, Porto, Portugal" } }],
|
|
@@ -116,7 +116,7 @@ function query4(qyDB) {
|
|
|
116
116
|
}
|
|
117
117
|
function query5(qyDB) {
|
|
118
118
|
console.time("query5");
|
|
119
|
-
|
|
119
|
+
deepEqual(
|
|
120
120
|
qyDB
|
|
121
121
|
.queryFilesMulti(
|
|
122
122
|
[
|
|
@@ -139,7 +139,7 @@ function query5(qyDB) {
|
|
|
139
139
|
}
|
|
140
140
|
function query6(qyDB) {
|
|
141
141
|
console.time("query6");
|
|
142
|
-
|
|
142
|
+
deepEqual(
|
|
143
143
|
qyDB
|
|
144
144
|
.queryFilesMulti(
|
|
145
145
|
[
|
|
@@ -168,7 +168,7 @@ function query6(qyDB) {
|
|
|
168
168
|
}
|
|
169
169
|
function query7(qyDB) {
|
|
170
170
|
console.time("query7");
|
|
171
|
-
|
|
171
|
+
deepEqual(
|
|
172
172
|
qyDB.queryFiles(["airbnb", "Loft", "**"], { minimum_nights: (x) => x >= 60 }).map((x) => x.view(["name"]).name),
|
|
173
173
|
["Romantic loft near historic center", "Brand New Luxury Downtown Studio"],
|
|
174
174
|
);
|
|
@@ -176,7 +176,7 @@ function query7(qyDB) {
|
|
|
176
176
|
}
|
|
177
177
|
function query8(qyDB) {
|
|
178
178
|
console.time("query8");
|
|
179
|
-
|
|
179
|
+
deepEqual(
|
|
180
180
|
qyDB
|
|
181
181
|
.queryFiles(["airbnb", "Loft", ""], { minimum_nights: (x) => x >= 60 }, 10, 10)
|
|
182
182
|
.map((x) => x.view(["name"]).name),
|
|
@@ -186,7 +186,7 @@ function query8(qyDB) {
|
|
|
186
186
|
}
|
|
187
187
|
function query9(qyDB) {
|
|
188
188
|
console.time("query9");
|
|
189
|
-
|
|
189
|
+
deepEqual(
|
|
190
190
|
qyDB
|
|
191
191
|
.queryFilesMulti(
|
|
192
192
|
[
|
|
@@ -228,4 +228,4 @@ function runQueries(qyDB) {
|
|
|
228
228
|
query9(qyDB);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
|
|
231
|
+
export { runQueries };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { deepEqual } from "node:assert/strict";
|
|
2
2
|
|
|
3
3
|
function query1(qyDB) {
|
|
4
4
|
console.time("query1");
|
|
5
|
-
|
|
5
|
+
deepEqual(
|
|
6
6
|
qyDB
|
|
7
7
|
.queryFiles("airbnb1", {
|
|
8
8
|
property_type: "Loft",
|
|
@@ -35,7 +35,7 @@ function query1(qyDB) {
|
|
|
35
35
|
}
|
|
36
36
|
function query2(qyDB) {
|
|
37
37
|
console.time("query2");
|
|
38
|
-
|
|
38
|
+
deepEqual(
|
|
39
39
|
qyDB
|
|
40
40
|
.queryFiles(
|
|
41
41
|
"airbnb1",
|
|
@@ -64,7 +64,7 @@ function query2(qyDB) {
|
|
|
64
64
|
}
|
|
65
65
|
function query3(qyDB) {
|
|
66
66
|
console.time("query3");
|
|
67
|
-
|
|
67
|
+
deepEqual(
|
|
68
68
|
qyDB
|
|
69
69
|
.queryFiles(
|
|
70
70
|
"airbnb1",
|
|
@@ -93,7 +93,7 @@ function query3(qyDB) {
|
|
|
93
93
|
}
|
|
94
94
|
function query4(qyDB) {
|
|
95
95
|
console.time("query4");
|
|
96
|
-
|
|
96
|
+
deepEqual(
|
|
97
97
|
qyDB
|
|
98
98
|
.queryFiles("airbnb1", {
|
|
99
99
|
$or: [
|
|
@@ -106,7 +106,8 @@ function query4(qyDB) {
|
|
|
106
106
|
{ property_type: (x) => x == "Loft", minimum_nights: (x) => x >= 60 },
|
|
107
107
|
],
|
|
108
108
|
})
|
|
109
|
-
.map((x) => x.view(["name"]).name)
|
|
109
|
+
.map((x) => x.view(["name"]).name)
|
|
110
|
+
.sort(),
|
|
110
111
|
[
|
|
111
112
|
"Porto city centre apartment H",
|
|
112
113
|
"Romantic loft near historic center",
|
|
@@ -126,13 +127,13 @@ function query4(qyDB) {
|
|
|
126
127
|
"Your OWM Invicta",
|
|
127
128
|
"Pury Apartments",
|
|
128
129
|
"Live Porto & Douro - Breiner III",
|
|
129
|
-
],
|
|
130
|
+
].sort(),
|
|
130
131
|
);
|
|
131
132
|
console.timeEnd("query4");
|
|
132
133
|
}
|
|
133
134
|
function query5(qyDB) {
|
|
134
135
|
console.time("query5");
|
|
135
|
-
|
|
136
|
+
deepEqual(
|
|
136
137
|
qyDB
|
|
137
138
|
.queryFiles(
|
|
138
139
|
"airbnb1",
|
|
@@ -160,7 +161,7 @@ function query5(qyDB) {
|
|
|
160
161
|
}
|
|
161
162
|
function query6(qyDB) {
|
|
162
163
|
console.time("query6");
|
|
163
|
-
|
|
164
|
+
deepEqual(
|
|
164
165
|
qyDB
|
|
165
166
|
.queryFiles(
|
|
166
167
|
"airbnb1",
|
|
@@ -180,7 +181,6 @@ function query6(qyDB) {
|
|
|
180
181
|
)
|
|
181
182
|
.map((x) => x.view(["name"]).name),
|
|
182
183
|
[
|
|
183
|
-
"Bright Top Floor Two Rooms Apartment w/ Terrace",
|
|
184
184
|
"ReUrban Flats - Santa Catarina #3",
|
|
185
185
|
"The Blue and White Porto House - Vintage",
|
|
186
186
|
"4twoLoft at Great Location",
|
|
@@ -188,13 +188,14 @@ function query6(qyDB) {
|
|
|
188
188
|
"Your OWM Invicta",
|
|
189
189
|
"Pury Apartments",
|
|
190
190
|
"Live Porto & Douro - Breiner III",
|
|
191
|
+
"Brand New Luxury Downtown Studio",
|
|
191
192
|
],
|
|
192
193
|
);
|
|
193
194
|
console.timeEnd("query6");
|
|
194
195
|
}
|
|
195
196
|
function query7(qyDB) {
|
|
196
197
|
console.time("query7");
|
|
197
|
-
|
|
198
|
+
deepEqual(
|
|
198
199
|
qyDB
|
|
199
200
|
.queryFiles("airbnb1", { property_type: (x) => x == "Loft", minimum_nights: (x) => x >= 60 })
|
|
200
201
|
.map((x) => x.view(["name"]).name),
|
|
@@ -204,7 +205,7 @@ function query7(qyDB) {
|
|
|
204
205
|
}
|
|
205
206
|
function query8(qyDB) {
|
|
206
207
|
console.time("query8");
|
|
207
|
-
|
|
208
|
+
deepEqual(
|
|
208
209
|
qyDB
|
|
209
210
|
.queryFiles("airbnb1", { property_type: (x) => x == "Loft", minimum_nights: (x) => x >= 60 }, 10, 10)
|
|
210
211
|
.map((x) => x.view(["name"]).name),
|
|
@@ -214,7 +215,7 @@ function query8(qyDB) {
|
|
|
214
215
|
}
|
|
215
216
|
function query9(qyDB) {
|
|
216
217
|
console.time("query9");
|
|
217
|
-
|
|
218
|
+
deepEqual(
|
|
218
219
|
qyDB
|
|
219
220
|
.queryFiles(
|
|
220
221
|
"airbnb1",
|
|
@@ -261,4 +262,4 @@ function runQueries(qyDB) {
|
|
|
261
262
|
query9(qyDB);
|
|
262
263
|
}
|
|
263
264
|
|
|
264
|
-
|
|
265
|
+
export { runQueries };
|
package/scripts/downloadFile.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { createWriteStream } from "fs";
|
|
2
|
+
import { get } from "https";
|
|
3
|
+
import { ensureParentDir, folderOrFileExists } from "../src/QyUtils.js";
|
|
4
|
+
import { logger } from "../src/QyLogger.js";
|
|
5
5
|
|
|
6
6
|
async function downloadFile(fileUrl, filePath) {
|
|
7
7
|
if (await folderOrFileExists(filePath)) return;
|
|
@@ -11,32 +11,30 @@ async function downloadFile(fileUrl, filePath) {
|
|
|
11
11
|
resolve = res;
|
|
12
12
|
reject = rej;
|
|
13
13
|
});
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
reject(err.message);
|
|
39
|
-
});
|
|
14
|
+
get(fileUrl, (response) => {
|
|
15
|
+
if (response.statusCode !== 200) {
|
|
16
|
+
logger.error(`Download failed: Status Code ${response.statusCode}`);
|
|
17
|
+
reject(response.statusCode);
|
|
18
|
+
} else {
|
|
19
|
+
const fileStream = createWriteStream(filePath);
|
|
20
|
+
let accu = 0;
|
|
21
|
+
response.on("data", (chunk) => {
|
|
22
|
+
fileStream.write(chunk);
|
|
23
|
+
accu += chunk.length;
|
|
24
|
+
if (accu >= 1000_000) {
|
|
25
|
+
process.stdout.write(".");
|
|
26
|
+
accu = 0;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
response.on("end", () => {
|
|
30
|
+
fileStream.close();
|
|
31
|
+
resolve();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}).on("error", (err) => {
|
|
35
|
+
logger.error(`Request error: ${err.message}`);
|
|
36
|
+
reject(err.message);
|
|
37
|
+
});
|
|
40
38
|
return promise;
|
|
41
39
|
}
|
|
42
|
-
|
|
40
|
+
export { downloadFile };
|
package/scripts/express.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { QyDB } from "../src/QyDB.js";
|
|
3
|
+
import { __dirname } from "../src/QyUtils.js";
|
|
3
4
|
|
|
4
5
|
const config = {
|
|
5
6
|
port: 3629,
|
|
6
7
|
qyDBDataFolder: "./tmp/QyExpress",
|
|
7
|
-
staticRoot:
|
|
8
|
-
rpcFolder:
|
|
8
|
+
staticRoot: join(__dirname, "../static/"),
|
|
9
|
+
rpcFolder: join(__dirname, "rpc"),
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
const { port, qyDBDataFolder } = config;
|
package/scripts/fastify.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import { join, basename } from "node:path";
|
|
3
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
4
|
+
import fastifyStatic from "@fastify/static";
|
|
5
|
+
import fastifyCompress from "@fastify/compress";
|
|
6
|
+
import { QyDB } from "../src/QyDB.js";
|
|
7
|
+
import { folderOrFileExists, __dirname } from "../src/QyUtils.js";
|
|
8
|
+
import Fastify from "fastify";
|
|
8
9
|
|
|
9
10
|
const config = {
|
|
10
11
|
port: 3628,
|
|
11
|
-
staticRoot:
|
|
12
|
-
rpcFolder:
|
|
12
|
+
staticRoot: join(__dirname, "../static/"),
|
|
13
|
+
rpcFolder: join(__dirname, "../src/rpc"),
|
|
13
14
|
};
|
|
14
15
|
const { port, staticRoot } = config;
|
|
15
16
|
|
|
16
|
-
const fastify =
|
|
17
|
+
const fastify = Fastify({ logger: false, forceCloseConnections: true });
|
|
17
18
|
|
|
18
19
|
const qyDB = new QyDB();
|
|
19
20
|
|
|
@@ -35,8 +36,8 @@ async function insertRpcs() {
|
|
|
35
36
|
const { rpcFolder } = config;
|
|
36
37
|
if (await folderOrFileExists(rpcFolder)) {
|
|
37
38
|
await Promise.all(
|
|
38
|
-
(await
|
|
39
|
-
qyDB.insertRpc(
|
|
39
|
+
(await readdir(rpcFolder)).map(async (x) => {
|
|
40
|
+
qyDB.insertRpc(basename(x, ".js"), (await readFile(join(rpcFolder, x))).toString());
|
|
40
41
|
}),
|
|
41
42
|
);
|
|
42
43
|
}
|
package/scripts/flights.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// node --prof profile.js
|
|
2
2
|
// node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { rm } from "node:fs/promises";
|
|
6
|
+
import { QyDB } from "../src/QyDB.js";
|
|
7
|
+
import { folderOrFileExists } from "../src/QyUtils.js";
|
|
8
|
+
import { runQueries } from "./flights_queries.js";
|
|
9
9
|
|
|
10
10
|
logger.level = "info";
|
|
11
11
|
|
|
@@ -17,7 +17,7 @@ const qyDB = new QyDB(dataFolder, { preloadFoldersAtStart: false });
|
|
|
17
17
|
run();
|
|
18
18
|
|
|
19
19
|
function insertAirports() {
|
|
20
|
-
const data = JSON.parse(
|
|
20
|
+
const data = JSON.parse(readFileSync(join(arangoJsonFolderPath, "airports.json")));
|
|
21
21
|
console.time("insertAirports");
|
|
22
22
|
const { batch } = qyDB;
|
|
23
23
|
for (const record of data) {
|
|
@@ -28,7 +28,7 @@ function insertAirports() {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
function insertFlights() {
|
|
31
|
-
const data = JSON.parse(
|
|
31
|
+
const data = JSON.parse(readFileSync(join(arangoJsonFolderPath, "flights.json")));
|
|
32
32
|
console.time("insertFlights");
|
|
33
33
|
const { batch } = qyDB;
|
|
34
34
|
for (let i = 0; i < data.length; ++i) {
|
package/scripts/flights2.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
// node --prof profile.js
|
|
2
2
|
// node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { rm } from "node:fs/promises";
|
|
6
|
+
import { QyDB } from "../src/QyDB.js";
|
|
7
|
+
import { folderOrFileExists } from "../src/QyUtils.js";
|
|
8
|
+
import { runQueries } from "./flights2_queries.js";
|
|
9
9
|
|
|
10
10
|
logger.level = "info";
|
|
11
11
|
|
|
12
|
-
const arangoJsonFolderPath = "
|
|
12
|
+
const arangoJsonFolderPath = "D:\\scripts\\GraphCourse_DemoData_ArangoDB-2";
|
|
13
13
|
const dataFolder = "./tmp/flights2";
|
|
14
14
|
const qyDB = new QyDB(dataFolder, { preloadFoldersAtStart: false });
|
|
15
15
|
|
|
16
16
|
run();
|
|
17
17
|
|
|
18
18
|
function insertAirports() {
|
|
19
|
-
const data = JSON.parse(
|
|
19
|
+
const data = JSON.parse(readFileSync(join(arangoJsonFolderPath, "airports.json")));
|
|
20
20
|
console.time("insertAirports");
|
|
21
21
|
const { batch } = qyDB;
|
|
22
22
|
for (const record of data) {
|
|
@@ -28,7 +28,7 @@ function insertAirports() {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
function insertFlights() {
|
|
31
|
-
const data = JSON.parse(
|
|
31
|
+
const data = JSON.parse(readFileSync(join(arangoJsonFolderPath, "flights.json")));
|
|
32
32
|
console.time("insertFlights");
|
|
33
33
|
const { batch } = qyDB;
|
|
34
34
|
for (let i = 0; i < data.length; ++i) {
|