datafolder 1.0.2 → 1.0.4
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 +34 -31
- package/index.js +1 -3
- package/package.json +5 -3
- package/sample.js +37 -37
- package/scripts/airbnb.js +10 -11
- package/scripts/airbnb2.js +10 -11
- package/scripts/airbnb2_queries.js +20 -22
- package/scripts/airbnb_queries.js +23 -22
- package/scripts/downloadFile.js +29 -31
- package/scripts/express.js +7 -5
- package/scripts/fastify.js +12 -11
- package/scripts/flights.js +9 -9
- package/scripts/flights2.js +9 -9
- package/scripts/flights2_queries.js +107 -105
- package/scripts/flights_queries.js +113 -109
- 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 +67 -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 +264 -242
- 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 +12 -28
- package/src/rpc/queryFiles.js +2 -25
- 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/query-editor.js +6 -1
- package/static/datafolderui/querySelectorShadowRoot.js +15 -19
- package/static/datafolderui/resizable-input.js +18 -18
package/README.md
CHANGED
|
@@ -11,33 +11,29 @@ 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();
|
|
17
|
-
dataFolder.insert("
|
|
16
|
+
await dataFolder.start(); //start() and stop() are the only two async places. All other code doesn't need await.
|
|
17
|
+
dataFolder.insert("traindata/2026/1/20/chat_0001", {
|
|
18
18
|
userid: "user_0001",
|
|
19
19
|
email: "a@b.com",
|
|
20
|
-
|
|
20
|
+
feedbackScore: 5,
|
|
21
21
|
address: { city: "a", zipcode: 123 },
|
|
22
22
|
});
|
|
23
|
-
dataFolder.insert("
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
score: 3,
|
|
27
|
-
address: { city: "b", zipcode: 321 },
|
|
28
|
-
});
|
|
29
|
-
const { email, password, address, score } = dataFolder.view("users/2026/user_0002");
|
|
23
|
+
dataFolder.insert("traindata/2026/1/20/chat_0001/prompt", "What is async/await?");
|
|
24
|
+
dataFolder.insert("traindata/2026/1/20/chat_0001/answer", "async/await is ...");
|
|
25
|
+
const { email, password, address, feedbackScore } = dataFolder.view("traindata/2026/1/20/chat_0001");
|
|
30
26
|
address.zipcode = 678;
|
|
31
|
-
dataFolder.insert("
|
|
27
|
+
dataFolder.insert("traindata/2026/1/20/chat_0001", { feedbackScore: feedbackScore + 1, address });
|
|
32
28
|
await dataFolder.stop();
|
|
33
29
|
```
|
|
34
30
|
|
|
35
31
|
Or operate with dir/file objects:
|
|
36
32
|
|
|
37
33
|
```javascript
|
|
38
|
-
const file = dataFolder.file("
|
|
39
|
-
const {
|
|
40
|
-
dataFolder.insert(file, {
|
|
34
|
+
const file = dataFolder.file("traindata/2026/1/20/chat_0001");
|
|
35
|
+
const { feedbackScore, address } = file.view({ feedbackScore: 1, address: 1 });
|
|
36
|
+
dataFolder.insert(file, { feedbackScore: feedbackScore + 1, address: { city: "c", zipcode: 663 } });
|
|
41
37
|
```
|
|
42
38
|
|
|
43
39
|
## Features
|
|
@@ -75,7 +71,7 @@ const { email, address } = dataFolder.view("path/to/file", { email: 1, addres: 1
|
|
|
75
71
|
|
|
76
72
|
```javascript
|
|
77
73
|
dataFolder.insert("path/to/file", { email: newEmail, address: { zipcode: newZipcode } });
|
|
78
|
-
dataFolder.insert(file, {
|
|
74
|
+
dataFolder.insert(file, { feedbackScore: feedbackScore + 1 });
|
|
79
75
|
```
|
|
80
76
|
|
|
81
77
|
#### Delete
|
|
@@ -91,14 +87,15 @@ dataFolder.remove(file, { email: 1, address: { zipcode: 1 } });
|
|
|
91
87
|
### 2. Batch APIs
|
|
92
88
|
|
|
93
89
|
```javascript
|
|
94
|
-
const [dir, file, { email,
|
|
90
|
+
const [dir, file, { email, feedbackScore }] = dataFolder.fetch
|
|
95
91
|
.dir("path/to/dir")
|
|
96
92
|
.file("path/to/file")
|
|
97
93
|
.view("path/to/file")
|
|
98
94
|
.run();
|
|
99
95
|
dataFolder.batch
|
|
100
|
-
.insert("path/to/
|
|
101
|
-
.insert("path/to/
|
|
96
|
+
.insert("path/to/chat_details", { user: "user_0001", feedbackScore: 100 })
|
|
97
|
+
.insert("path/to/prompt", "what is LLM?")
|
|
98
|
+
.insert("path/to/answer", "LLM is AI...")
|
|
102
99
|
.remove("path/to/file", { address: { city: 1 } })
|
|
103
100
|
.run();
|
|
104
101
|
```
|
|
@@ -107,7 +104,13 @@ dataFolder.batch
|
|
|
107
104
|
|
|
108
105
|
```javascript
|
|
109
106
|
dataFolder.queryFiles("flights/**", { _from: "airports/LAX" });
|
|
110
|
-
dataFolder.queryFiles(["flights", "*",
|
|
107
|
+
dataFolder.queryFiles(["flights", "*", "jan", (x) => x >= 5 && x <= 7], {
|
|
108
|
+
$or: [{ _from: "airports/BIS" }, { _to: "airports/BIS" }],
|
|
109
|
+
});
|
|
110
|
+
dataFolder.queryFiles(["flights", "*", "feb", { $or: [5, 6, 7] }], {
|
|
111
|
+
$or: [{ _from: "airports/BIS" }, { _to: "airports/BIS" }],
|
|
112
|
+
});
|
|
113
|
+
dataFolder.queryFiles(["flights", "*", "mar", { $gte: 5, lte: 7 }], {
|
|
111
114
|
$or: [{ _from: "airports/BIS" }, { _to: "airports/BIS" }],
|
|
112
115
|
});
|
|
113
116
|
dataFolder.queryFilesMulti([
|
|
@@ -119,23 +122,23 @@ dataFolder.queryFilesMulti([
|
|
|
119
122
|
### 4. Flexible Trigger Support to Monitor Any Changes
|
|
120
123
|
|
|
121
124
|
```javascript
|
|
122
|
-
function
|
|
123
|
-
const { oldValue, newValue } =
|
|
124
|
-
// Logic to handle
|
|
125
|
+
function onPromptScoreChanged({ promptId, feedbackScore }) {
|
|
126
|
+
const { oldValue, newValue } = feedbackScore;
|
|
127
|
+
// Logic to handle prompt feedback score change.
|
|
125
128
|
}
|
|
126
|
-
dataFolder.insertTrigger("
|
|
127
|
-
dataFolder.on("
|
|
128
|
-
dataFolder.insert("
|
|
129
|
-
dataFolder.insert("
|
|
130
|
-
dataFolder.insert("
|
|
129
|
+
dataFolder.insertTrigger("promptScoreChanged", "traindata/{promptId}", "feedbackScore");
|
|
130
|
+
dataFolder.on("promptScoreChanged", onPromptScoreChanged);
|
|
131
|
+
dataFolder.insert("traindata/prompt_1", { feedbackScore: 80 });
|
|
132
|
+
dataFolder.insert("traindata/prompt_2", { feedbackScore: 63 });
|
|
133
|
+
dataFolder.insert("traindata/prompt_1", { feedbackScore: 32 });
|
|
131
134
|
```
|
|
132
135
|
|
|
133
136
|
Will trigger the following calls:
|
|
134
137
|
|
|
135
138
|
```javascript
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
onPromptScoreChanged({ promptId: "student1", feedbackScore: { oldValue: undefined, newValue: 80 } });
|
|
140
|
+
onPromptScoreChanged({ promptId: "student2", feedbackScore: { oldValue: undefined, newValue: 63 } });
|
|
141
|
+
onPromptScoreChanged({ promptId: "student1", feedbackScore: { oldValue: 80, newValue: 32 } });
|
|
139
142
|
```
|
|
140
143
|
|
|
141
144
|
## Example
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "datafolder",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "lysh",
|
|
6
6
|
"email": "datafolderdev@outlook.com"
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"easy",
|
|
38
38
|
"quick",
|
|
39
39
|
"millisecond",
|
|
40
|
-
"lightweight"
|
|
40
|
+
"lightweight",
|
|
41
|
+
"LSM"
|
|
41
42
|
],
|
|
42
43
|
"dependencies": {},
|
|
43
44
|
"devDependencies": {
|
|
@@ -50,5 +51,6 @@
|
|
|
50
51
|
"scripts": {
|
|
51
52
|
"ui": "start http://localhost:3628/datafolderui/index.html && node ./scripts/fastify.js",
|
|
52
53
|
"airbnb": "node ./scripts/airbnb2.js && start http://localhost:3628/datafolderui/index.html && node ./scripts/fastify.js"
|
|
53
|
-
}
|
|
54
|
+
},
|
|
55
|
+
"type": "module"
|
|
54
56
|
}
|
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,13 +1,13 @@
|
|
|
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" },
|
|
9
9
|
})
|
|
10
|
-
.map((x) => x.
|
|
10
|
+
.map((x) => x.prop("name")),
|
|
11
11
|
[
|
|
12
12
|
"Porto city centre apartment H",
|
|
13
13
|
"Romantic loft near historic center",
|
|
@@ -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"],
|
|
@@ -41,7 +41,7 @@ function query2(qyDB) {
|
|
|
41
41
|
},
|
|
42
42
|
9,
|
|
43
43
|
)
|
|
44
|
-
.map((x) => x.
|
|
44
|
+
.map((x) => x.prop("name")),
|
|
45
45
|
[
|
|
46
46
|
"Porto city centre apartment H",
|
|
47
47
|
"Romantic loft near historic center",
|
|
@@ -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"],
|
|
@@ -66,7 +66,7 @@ function query3(qyDB) {
|
|
|
66
66
|
9,
|
|
67
67
|
9,
|
|
68
68
|
)
|
|
69
|
-
.map((x) => x.
|
|
69
|
+
.map((x) => x.prop("name")),
|
|
70
70
|
[
|
|
71
71
|
"Bright Top Floor Two Rooms Apartment w/ Terrace",
|
|
72
72
|
"ReUrban Flats - Santa Catarina #3",
|
|
@@ -82,14 +82,14 @@ 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" } }],
|
|
89
89
|
["airbnb/Loft/**", { minimum_nights: (x) => x >= 60 }],
|
|
90
90
|
])
|
|
91
91
|
.run()[0]
|
|
92
|
-
.map((x) => x.
|
|
92
|
+
.map((x) => x.prop("name"))
|
|
93
93
|
.sort(),
|
|
94
94
|
[
|
|
95
95
|
"Porto city centre apartment H",
|
|
@@ -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
|
[
|
|
@@ -128,7 +128,7 @@ function query5(qyDB) {
|
|
|
128
128
|
],
|
|
129
129
|
3,
|
|
130
130
|
)
|
|
131
|
-
.map((x) => x.
|
|
131
|
+
.map((x) => x.prop("name")),
|
|
132
132
|
[
|
|
133
133
|
"Porto city centre apartment H",
|
|
134
134
|
"Romantic loft near historic center",
|
|
@@ -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
|
[
|
|
@@ -152,7 +152,7 @@ function query6(qyDB) {
|
|
|
152
152
|
20,
|
|
153
153
|
10,
|
|
154
154
|
)
|
|
155
|
-
.map((x) => x.
|
|
155
|
+
.map((x) => x.prop("name")),
|
|
156
156
|
[
|
|
157
157
|
"ReUrban Flats - Santa Catarina #3",
|
|
158
158
|
"The Blue and White Porto House - Vintage",
|
|
@@ -168,25 +168,23 @@ function query6(qyDB) {
|
|
|
168
168
|
}
|
|
169
169
|
function query7(qyDB) {
|
|
170
170
|
console.time("query7");
|
|
171
|
-
|
|
172
|
-
qyDB.queryFiles(["airbnb", "Loft", "**"], { minimum_nights: (x) => x >= 60 }).map((x) => x.
|
|
171
|
+
deepEqual(
|
|
172
|
+
qyDB.queryFiles(["airbnb", "Loft", "**"], { minimum_nights: (x) => x >= 60 }).map((x) => x.prop("name")),
|
|
173
173
|
["Romantic loft near historic center", "Brand New Luxury Downtown Studio"],
|
|
174
174
|
);
|
|
175
175
|
console.timeEnd("query7");
|
|
176
176
|
}
|
|
177
177
|
function query8(qyDB) {
|
|
178
178
|
console.time("query8");
|
|
179
|
-
|
|
180
|
-
qyDB
|
|
181
|
-
.queryFiles(["airbnb", "Loft", ""], { minimum_nights: (x) => x >= 60 }, 10, 10)
|
|
182
|
-
.map((x) => x.view(["name"]).name),
|
|
179
|
+
deepEqual(
|
|
180
|
+
qyDB.queryFiles(["airbnb", "Loft", ""], { minimum_nights: (x) => x >= 60 }, 10, 10).map((x) => x.prop("name")),
|
|
183
181
|
[],
|
|
184
182
|
);
|
|
185
183
|
console.timeEnd("query8");
|
|
186
184
|
}
|
|
187
185
|
function query9(qyDB) {
|
|
188
186
|
console.time("query9");
|
|
189
|
-
|
|
187
|
+
deepEqual(
|
|
190
188
|
qyDB
|
|
191
189
|
.queryFilesMulti(
|
|
192
190
|
[
|
|
@@ -198,7 +196,7 @@ function query9(qyDB) {
|
|
|
198
196
|
],
|
|
199
197
|
3,
|
|
200
198
|
)
|
|
201
|
-
.map((x) => x.
|
|
199
|
+
.map((x) => x.prop("name")),
|
|
202
200
|
[
|
|
203
201
|
"Porto city centre apartment H",
|
|
204
202
|
"Romantic loft near historic center",
|
|
@@ -228,4 +226,4 @@ function runQueries(qyDB) {
|
|
|
228
226
|
query9(qyDB);
|
|
229
227
|
}
|
|
230
228
|
|
|
231
|
-
|
|
229
|
+
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",
|
|
@@ -10,7 +10,7 @@ function query1(qyDB) {
|
|
|
10
10
|
bed_type: "Real Bed",
|
|
11
11
|
address: { street: "Porto, Porto, Portugal" },
|
|
12
12
|
})
|
|
13
|
-
.map((x) => x.
|
|
13
|
+
.map((x) => x.prop("name")),
|
|
14
14
|
[
|
|
15
15
|
"Porto city centre apartment H",
|
|
16
16
|
"Romantic loft near historic center",
|
|
@@ -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",
|
|
@@ -47,7 +47,7 @@ function query2(qyDB) {
|
|
|
47
47
|
},
|
|
48
48
|
9,
|
|
49
49
|
)
|
|
50
|
-
.map((x) => x.
|
|
50
|
+
.map((x) => x.prop("name")),
|
|
51
51
|
[
|
|
52
52
|
"Porto city centre apartment H",
|
|
53
53
|
"Romantic loft near historic center",
|
|
@@ -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",
|
|
@@ -77,7 +77,7 @@ function query3(qyDB) {
|
|
|
77
77
|
9,
|
|
78
78
|
9,
|
|
79
79
|
)
|
|
80
|
-
.map((x) => x.
|
|
80
|
+
.map((x) => x.prop("name")),
|
|
81
81
|
[
|
|
82
82
|
"Bright Top Floor Two Rooms Apartment w/ Terrace",
|
|
83
83
|
"ReUrban Flats - Santa Catarina #3",
|
|
@@ -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.
|
|
109
|
+
.map((x) => x.prop("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",
|
|
@@ -149,7 +150,7 @@ function query5(qyDB) {
|
|
|
149
150
|
},
|
|
150
151
|
3,
|
|
151
152
|
)
|
|
152
|
-
.map((x) => x.
|
|
153
|
+
.map((x) => x.prop("name")),
|
|
153
154
|
[
|
|
154
155
|
"Porto city centre apartment H",
|
|
155
156
|
"Romantic loft near historic center",
|
|
@@ -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",
|
|
@@ -178,9 +179,8 @@ function query6(qyDB) {
|
|
|
178
179
|
20,
|
|
179
180
|
10,
|
|
180
181
|
)
|
|
181
|
-
.map((x) => x.
|
|
182
|
+
.map((x) => x.prop("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,33 +188,34 @@ 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
|
-
.map((x) => x.
|
|
201
|
+
.map((x) => x.prop("name")),
|
|
201
202
|
["Romantic loft near historic center", "Brand New Luxury Downtown Studio"],
|
|
202
203
|
);
|
|
203
204
|
console.timeEnd("query7");
|
|
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
|
-
.map((x) => x.
|
|
211
|
+
.map((x) => x.prop("name")),
|
|
211
212
|
[],
|
|
212
213
|
);
|
|
213
214
|
console.timeEnd("query8");
|
|
214
215
|
}
|
|
215
216
|
function query9(qyDB) {
|
|
216
217
|
console.time("query9");
|
|
217
|
-
|
|
218
|
+
deepEqual(
|
|
218
219
|
qyDB
|
|
219
220
|
.queryFiles(
|
|
220
221
|
"airbnb1",
|
|
@@ -231,7 +232,7 @@ function query9(qyDB) {
|
|
|
231
232
|
},
|
|
232
233
|
3,
|
|
233
234
|
)
|
|
234
|
-
.map((x) => x.
|
|
235
|
+
.map((x) => x.prop("name")),
|
|
235
236
|
[
|
|
236
237
|
"Porto city centre apartment H",
|
|
237
238
|
"Romantic loft near historic center",
|
|
@@ -261,4 +262,4 @@ function runQueries(qyDB) {
|
|
|
261
262
|
query9(qyDB);
|
|
262
263
|
}
|
|
263
264
|
|
|
264
|
-
|
|
265
|
+
export { runQueries };
|