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 CHANGED
@@ -99,92 +99,32 @@ const ids = await db.insertBatch([
99
99
 
100
100
  ### Querying
101
101
 
102
- `document-dataply` supports various comparison operators.
102
+ `document-dataply` supports powerful search capabilities based on B+Tree indexing.
103
103
 
104
104
  | Operator | Description |
105
105
  | :--- | :--- |
106
- | `lt` | Less than |
107
- | `lte` | Less than or equal to |
108
- | `gt` | Greater than |
109
- | `gte` | Greater than or equal to |
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
- > [!IMPORTANT]
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
- To ensure the atomicity of multiple operations, use transactions.
115
+ Ensure data integrity with ACID-compliant transactions. Use `commit()` and `rollback()` to process multiple operations atomically.
138
116
 
139
- ```typescript
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 matching a query. All these operations are performed in a memory-efficient streaming manner.
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
- #### Partial Update
156
- Updates only specified fields of the matching documents.
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
- ```typescript
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. Returns the `_id` (`number`) of the 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 ?? "_id";
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
- orderByTree ? orderBy : void 0
10040
+ orderBy
10042
10041
  );
10043
10042
  if (!selectivity) return;
10044
10043
  const { driver, others } = selectivity;
10045
- const isDriverOrderByField = orderByTree && driver.field === orderBy;
10044
+ const isDriverOrderByField = orderBy === void 0 || driver.field === orderBy;
10046
10045
  if (isDriverOrderByField) {
10047
- const driverStream = driver.tree.whereStream(driver.condition, limit, sortOrder);
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 await (const [pk, val] of driverStream) {
10051
+ for (const key of keys) {
10050
10052
  if (i >= limit) break;
10051
- let isMatch = true;
10052
- for (const { tree, condition } of others) {
10053
- const targetValue = await tree.get(pk);
10054
- if (targetValue === void 0 || !tree.verify(targetValue, condition)) {
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
- const driverStream = driver.tree.whereStream(driver.condition);
10069
- for await (const [pk, val] of driverStream) {
10070
- let isMatch = true;
10071
- for (const { tree, condition } of others) {
10072
- const targetValue = await tree.get(pk);
10073
- if (targetValue === void 0 || !tree.verify(targetValue, condition)) {
10074
- isMatch = false;
10075
- break;
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.0",
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>",