document-dataply 0.0.3-alpha.0 → 0.0.3-alpha.1
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 +15 -75
- package/dist/cjs/index.js +21 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,92 +99,32 @@ const ids = await db.insertBatch([
|
|
|
99
99
|
|
|
100
100
|
### Querying
|
|
101
101
|
|
|
102
|
-
`document-dataply` supports
|
|
102
|
+
`document-dataply` supports powerful search capabilities based on B+Tree indexing.
|
|
103
103
|
|
|
104
104
|
| Operator | Description |
|
|
105
105
|
| :--- | :--- |
|
|
106
|
-
| `lt` |
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
109
|
-
| `
|
|
110
|
-
| `equal` | Equal to |
|
|
111
|
-
| `notEqual` | Not equal to |
|
|
112
|
-
| `like` | SQL-style pattern matching (e.g., `Jo%`) |
|
|
113
|
-
| `or` | If any value in the array is satisfied |
|
|
114
|
-
|
|
115
|
-
Example of a complex query:
|
|
116
|
-
```typescript
|
|
117
|
-
const users = await db.select({
|
|
118
|
-
age: { gt: 18, lt: 65 },
|
|
119
|
-
'address.city': 'Seoul',
|
|
120
|
-
tags: { or: ['vip', 'premium'] }
|
|
121
|
-
}).drain();
|
|
122
|
-
```
|
|
106
|
+
| `lt`, `lte`, `gt`, `gte` | Comparison operations |
|
|
107
|
+
| `equal`, `notEqual` | Equality check |
|
|
108
|
+
| `like` | Pattern matching |
|
|
109
|
+
| `or` | Matching within an array |
|
|
123
110
|
|
|
124
|
-
|
|
125
|
-
> **Query Constraints**: Query conditions (`lt`, `gt`, `equal`, etc.) can only be used on fields explicitly indexed during initialization.
|
|
126
|
-
>
|
|
127
|
-
> **If a field in the query is not indexed, that condition will be ignored.**
|
|
128
|
-
>
|
|
129
|
-
> If you need to filter by unindexed fields, you should first retrieve the documents and then use JavaScript's native `.filter()` method.
|
|
130
|
-
```typescript
|
|
131
|
-
const results = await db.select({ /* indexed fields only */ }).drain();
|
|
132
|
-
const filtered = results.filter(doc => doc.unindexedField === 'some-value');
|
|
133
|
-
```
|
|
111
|
+
For detailed operator usage, index constraints (including full scans), and sorting methods, see the [Query Guide (QUERY.md)](./docs/QUERY.md).
|
|
134
112
|
|
|
135
113
|
### Transactions
|
|
136
114
|
|
|
137
|
-
|
|
115
|
+
Ensure data integrity with ACID-compliant transactions. Use `commit()` and `rollback()` to process multiple operations atomically.
|
|
138
116
|
|
|
139
|
-
|
|
140
|
-
const tx = db.createTransaction();
|
|
141
|
-
try {
|
|
142
|
-
await db.insert({ name: 'Alice', age: 25 }, tx);
|
|
143
|
-
await db.insert({ name: 'Bob', age: 28 }, tx);
|
|
144
|
-
await tx.commit();
|
|
145
|
-
} catch (error) {
|
|
146
|
-
await tx.rollback();
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
```
|
|
117
|
+
For detailed usage and error handling patterns, see the [Transaction Guide (TRANSACTION.md)](./docs/TRANSACTION.md).
|
|
150
118
|
|
|
151
119
|
### Updating and Deleting
|
|
152
120
|
|
|
153
|
-
`document-dataply` provides flexible ways to update or delete documents
|
|
121
|
+
`document-dataply` provides flexible ways to update or delete documents based on query results. All these operations are **Stream-based**, allowing you to handle millions of records without memory concerns.
|
|
154
122
|
|
|
155
|
-
|
|
156
|
-
|
|
123
|
+
- **Partial Update**: Modify only specific fields or use a function for dynamic updates.
|
|
124
|
+
- **Full Update**: Replace the entire document while preserving the original `_id`.
|
|
125
|
+
- **Delete**: Permanently remove matching documents from both storage and indices.
|
|
157
126
|
|
|
158
|
-
|
|
159
|
-
// Using an object to merge
|
|
160
|
-
const count = await db.partialUpdate(
|
|
161
|
-
{ name: 'John Doe' },
|
|
162
|
-
{ status: 'active', updatedAt: Date.now() }
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
// Using a function for dynamic updates
|
|
166
|
-
const count = await db.partialUpdate(
|
|
167
|
-
{ age: { lt: 20 } },
|
|
168
|
-
(doc) => ({ age: doc.age + 1 })
|
|
169
|
-
);
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
#### Full Update
|
|
173
|
-
Completely replaces the documents matching the query, while preserving their original `_id`.
|
|
174
|
-
|
|
175
|
-
```typescript
|
|
176
|
-
const count = await db.fullUpdate(
|
|
177
|
-
{ name: 'John Doe' },
|
|
178
|
-
{ name: 'John Smith', age: 31, location: 'New York' }
|
|
179
|
-
);
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
#### Delete
|
|
183
|
-
Removes documents matching the query from both the index and storage.
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
const deletedCount = await db.delete({ status: 'inactive' });
|
|
187
|
-
```
|
|
127
|
+
For details on streaming mechanisms and bandwidth optimization tips, see the [Stream Guide (STREAM.md)](./docs/STREAM.md).
|
|
188
128
|
|
|
189
129
|
## Tips and Advanced Features
|
|
190
130
|
|
|
@@ -206,13 +146,13 @@ Creates or opens a database instance. `T` defines the document structure.
|
|
|
206
146
|
Initializes the database, sets up internal metadata, and prepares indices.
|
|
207
147
|
|
|
208
148
|
### `db.insert(document, tx?)`
|
|
209
|
-
Inserts a single document.
|
|
149
|
+
Inserts a single document. Each document is automatically assigned a unique, immutable `_id` field. The method returns this `_id` (`number`).
|
|
210
150
|
|
|
211
151
|
### `db.insertBatch(documents, tx?)`
|
|
212
152
|
Inserts multiple documents efficiently. Returns an array of `_ids` (`number[]`).
|
|
213
153
|
|
|
214
154
|
### `db.select(query, options?, tx?)`
|
|
215
|
-
Searches for documents matching the query.
|
|
155
|
+
Searches for documents matching the query. Passing an empty object (`{}`) as the `query` retrieves all documents.
|
|
216
156
|
Returns an object `{ stream, drain }`.
|
|
217
157
|
- `stream`: An async iterator to traverse results one by one.
|
|
218
158
|
- `drain()`: A promise that resolves to an array of all matching documents.
|
package/dist/cjs/index.js
CHANGED
|
@@ -10022,8 +10022,8 @@ var DocumentDataply = class _DocumentDataply {
|
|
|
10022
10022
|
throw new Error(`Query field "${field}" is not indexed. Available indexed fields: ${Array.from(this.indexedFields).join(", ")}`);
|
|
10023
10023
|
}
|
|
10024
10024
|
}
|
|
10025
|
-
const orderBy = options.orderBy
|
|
10026
|
-
if (!this.indexedFields.has(orderBy)) {
|
|
10025
|
+
const orderBy = options.orderBy;
|
|
10026
|
+
if (orderBy !== void 0 && !this.indexedFields.has(orderBy)) {
|
|
10027
10027
|
throw new Error(`orderBy field "${orderBy}" is not indexed. Available indexed fields: ${Array.from(this.indexedFields).join(", ")}`);
|
|
10028
10028
|
}
|
|
10029
10029
|
const {
|
|
@@ -10035,51 +10035,36 @@ var DocumentDataply = class _DocumentDataply {
|
|
|
10035
10035
|
const isQueryEmpty = Object.keys(query).length === 0;
|
|
10036
10036
|
const normalizedQuery = isQueryEmpty ? { _id: { gte: 0 } } : query;
|
|
10037
10037
|
const verbose = self.verboseQuery(normalizedQuery);
|
|
10038
|
-
const orderByTree = self.api.trees.get(orderBy);
|
|
10039
10038
|
const selectivity = await self.getSelectivityCandidate(
|
|
10040
10039
|
verbose,
|
|
10041
|
-
|
|
10040
|
+
orderBy
|
|
10042
10041
|
);
|
|
10043
10042
|
if (!selectivity) return;
|
|
10044
10043
|
const { driver, others } = selectivity;
|
|
10045
|
-
const isDriverOrderByField =
|
|
10044
|
+
const isDriverOrderByField = orderBy === void 0 || driver.field === orderBy;
|
|
10046
10045
|
if (isDriverOrderByField) {
|
|
10047
|
-
|
|
10046
|
+
let keys = await driver.tree.keys(driver.condition, void 0, sortOrder);
|
|
10047
|
+
for (const { tree, condition } of others) {
|
|
10048
|
+
keys = await tree.keys(condition, keys, sortOrder);
|
|
10049
|
+
}
|
|
10048
10050
|
let i = 0;
|
|
10049
|
-
for
|
|
10051
|
+
for (const key of keys) {
|
|
10050
10052
|
if (i >= limit) break;
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
|
|
10055
|
-
isMatch = false;
|
|
10056
|
-
break;
|
|
10057
|
-
}
|
|
10058
|
-
}
|
|
10059
|
-
if (isMatch) {
|
|
10060
|
-
const stringified = await self.api.select(pk, false, tx2);
|
|
10061
|
-
if (!stringified) continue;
|
|
10062
|
-
yield JSON.parse(stringified);
|
|
10063
|
-
i++;
|
|
10064
|
-
}
|
|
10053
|
+
const stringified = await self.api.select(key, false, tx2);
|
|
10054
|
+
if (!stringified) continue;
|
|
10055
|
+
yield JSON.parse(stringified);
|
|
10056
|
+
i++;
|
|
10065
10057
|
}
|
|
10066
10058
|
} else {
|
|
10067
10059
|
const results = [];
|
|
10068
|
-
|
|
10069
|
-
for
|
|
10070
|
-
|
|
10071
|
-
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
}
|
|
10077
|
-
}
|
|
10078
|
-
if (isMatch) {
|
|
10079
|
-
const stringified = await self.api.select(pk, false, tx2);
|
|
10080
|
-
if (!stringified) continue;
|
|
10081
|
-
results.push(JSON.parse(stringified));
|
|
10082
|
-
}
|
|
10060
|
+
let keys = await driver.tree.keys(driver.condition, void 0);
|
|
10061
|
+
for (const { tree, condition } of others) {
|
|
10062
|
+
keys = await tree.keys(condition, keys);
|
|
10063
|
+
}
|
|
10064
|
+
for (const key of keys) {
|
|
10065
|
+
const stringified = await self.api.select(key, false, tx2);
|
|
10066
|
+
if (!stringified) continue;
|
|
10067
|
+
results.push(JSON.parse(stringified));
|
|
10083
10068
|
}
|
|
10084
10069
|
results.sort((a, b) => {
|
|
10085
10070
|
const aVal = a[orderBy] ?? a._id;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "document-dataply",
|
|
3
|
-
"version": "0.0.3-alpha.
|
|
3
|
+
"version": "0.0.3-alpha.1",
|
|
4
4
|
"description": "Simple and powerful JSON document database supporting complex queries and flexible indexing policies.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "izure <admin@izure.org>",
|