sorla-db 1.1.0 → 1.3.0
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 +152 -9
- package/dist/sorla.min.js +1 -1
- package/index.d.ts +157 -0
- package/index.mjs +5 -0
- package/package.json +27 -3
- package/src/dbs/database.js +48 -0
- package/src/documents/cursor.js +141 -25
- package/src/documents/document.js +26 -30
- package/src/events.js +69 -0
- package/src/query_language/manipulation.js +321 -50
- package/src/query_language/operators.js +66 -1
- package/src/query_language/query.js +6 -2
- package/src/query_language/update.js +167 -0
- package/src/sorla.js +27 -0
- package/src/utils.js +9 -8
- package/Brainstorming.md +0 -22
- package/debug-not.js +0 -24
- package/example/simple_data_example.html +0 -196
- package/index.js +0 -62
- package/src/helper.js +0 -41
- package/test/feature_collection.test.js +0 -75
- package/test/feature_collection_queries.test.js +0 -224
- package/test/feature_cursor.test.js +0 -84
- package/test/feature_database.test.js +0 -62
- package/test/feature_insert.test.js +0 -116
- package/test/feature_nested_queries.test.js +0 -94
- package/test/feature_query_equivalence.test.js +0 -165
- package/test/unit_database.test.js +0 -36
- package/test/unit_document.test.js +0 -39
- package/test/unit_operators.test.js +0 -78
- package/test/unit_sorla.test.js +0 -42
- package/test/unit_test.test.js +0 -25
- package/webpack.config.js +0 -11
package/README.md
CHANGED
|
@@ -3,24 +3,34 @@ A simple and temporary database focused to use in browser environment that will
|
|
|
3
3
|
|
|
4
4
|
This idea is from our founder #andmarruda that give this idea and alot of this idea are developed by him.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
7
8
|
```
|
|
8
|
-
|
|
9
|
+
npm install sorla-db
|
|
9
10
|
```
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
```js
|
|
13
|
+
// Node / bundlers
|
|
14
|
+
const sorla = require('sorla-db');
|
|
15
|
+
// or
|
|
16
|
+
import sorla from 'sorla-db';
|
|
14
17
|
```
|
|
15
|
-
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<!-- browser, 9.5 kB: registers window.sorla -->
|
|
21
|
+
<script src="https://cdn.jsdelivr.net/npm/sorla-db@1/dist/sorla.min.js"></script>
|
|
16
22
|
```
|
|
17
23
|
|
|
24
|
+
TypeScript declarations are included.
|
|
25
|
+
|
|
26
|
+
## Development
|
|
27
|
+
|
|
18
28
|
```
|
|
19
|
-
npm
|
|
29
|
+
npm install
|
|
30
|
+
npm test # jest
|
|
31
|
+
npm run build # dist/sorla.min.js
|
|
20
32
|
```
|
|
21
33
|
|
|
22
|
-
Soon some documentations....
|
|
23
|
-
|
|
24
34
|
Prohibited characters $ and .,
|
|
25
35
|
$ because is used to call operators and . because uses to search key inside a object's object
|
|
26
36
|
|
|
@@ -42,6 +52,123 @@ window.sorla.db.updatedTags.insertMany([
|
|
|
42
52
|
]);
|
|
43
53
|
```
|
|
44
54
|
|
|
55
|
+
## Inserting documents
|
|
56
|
+
|
|
57
|
+
`insertOne` stores a **copy** of the document and returns its `_id` (a uuid v4 when the document
|
|
58
|
+
has none). `insertMany` validates the whole array first, so an invalid document never leaves the
|
|
59
|
+
collection with half of the batch, and returns the ids.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
const id = window.sorla.db.updatedTags.insertOne({ name: 'Ana', nickname: null });
|
|
63
|
+
const ids = window.sorla.db.updatedTags.insertMany([{ name: 'Bia' }, { _id: 'custom', name: 'Caio' }]);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- `null` values are allowed, at any depth
|
|
67
|
+
- a duplicated `_id` throws
|
|
68
|
+
- keys with `$` or `.` throw, at any depth
|
|
69
|
+
- values must be cloneable (no functions or DOM nodes)
|
|
70
|
+
|
|
71
|
+
Documents returned by the collection are read-only: assigning a field throws.
|
|
72
|
+
|
|
73
|
+
## Reading results
|
|
74
|
+
|
|
75
|
+
`find()` returns a cursor:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
const cursor = window.sorla.db.updatedTags.find({ age: { $gte: 18 } });
|
|
79
|
+
cursor.length; // number of documents
|
|
80
|
+
cursor.first(); // data of the first one, null when empty
|
|
81
|
+
cursor.last(); // data of the last one, null when empty
|
|
82
|
+
cursor.toArray(); // plain copies
|
|
83
|
+
while(cursor.hasNext()) cursor.next();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`findOne()` returns the data of the first matching document, or `null`.
|
|
87
|
+
|
|
88
|
+
## Sorting
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
window.sorla.db.updatedTags.find({}).sort({ age: -1, name: 1 }).toArray();
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`1` is ascending and `-1` descending, and `"a.b"` paths work. `sort()` returns the cursor. Values of
|
|
95
|
+
different types follow MongoDB's order: missing and null, numbers, strings, objects, arrays,
|
|
96
|
+
booleans, dates. Strings compare by code point. Pass a collation to compare by language rules,
|
|
97
|
+
using the `Intl.Collator` options:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
cursor.sort({ name: 1 }, { collation: { locale: 'pt-BR', sensitivity: 'base', numeric: true } });
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Paging and projection
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
collection.find({}).sort({ age: 1 }).skip(20).limit(10).toArray();
|
|
107
|
+
collection.find({}, { name: 1, age: 1 }); // only name, age and _id
|
|
108
|
+
collection.find({}, { name: 1, _id: 0 }); // only name
|
|
109
|
+
collection.find({}, { password: 0 }); // everything except password
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`limit(0)` means no limit. Inclusion and exclusion cannot be mixed (except `_id`), and projection
|
|
113
|
+
works on top level fields.
|
|
114
|
+
|
|
115
|
+
## Updating documents
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
collection.updateOne({ _id: id }, { $set: { 'address.city': 'Recife' }, $inc: { visits: 1 } });
|
|
119
|
+
collection.updateMany({ active: false }, { $unset: { token: '' } });
|
|
120
|
+
collection.updateOne({ email: 'a@b.c' }, { $set: { name: 'Ana' } }, { upsert: true });
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
| Operator | Effect |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `$set` | sets fields, creating missing objects of `"a.b"` paths |
|
|
126
|
+
| `$unset` | removes fields |
|
|
127
|
+
| `$inc` | adds a number (missing fields start at 0) |
|
|
128
|
+
| `$push` | appends to an array, `{ $push: { tags: { $each: ['a', 'b'] } } }` appends several |
|
|
129
|
+
| `$pull` | removes array items equal to a value, matching a condition (`{ $in: [...] }`) or a sub document (`{ ok: false }`) |
|
|
130
|
+
|
|
131
|
+
They return `{ matchedCount, modifiedCount, upsertedId }`. Updates are applied to a copy first: if an
|
|
132
|
+
operator fails (for example `$inc` on a text field) no document changes. `_id` cannot change. With
|
|
133
|
+
`{ upsert: true }`, a document is inserted from the equality conditions of the filter when nothing matches.
|
|
134
|
+
|
|
135
|
+
`replaceOne(filter, document)` replaces the whole document and keeps its `_id`.
|
|
136
|
+
|
|
137
|
+
## Deleting and counting
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
collection.deleteOne({ _id: id }); // { deletedCount: 1 }
|
|
141
|
+
collection.deleteMany({ age: { $lt: 18 } });
|
|
142
|
+
collection.deleteMany({}); // empties the collection
|
|
143
|
+
collection.count(); // every document
|
|
144
|
+
collection.count({ active: true }); // matching documents, without copying them
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Change events
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
const off = collection.on('change', event => {
|
|
151
|
+
// event.type: 'insert' | 'update' | 'replace' | 'delete'
|
|
152
|
+
// event.ids, event.documents (copies), event.previous (before update / replace)
|
|
153
|
+
});
|
|
154
|
+
collection.on('delete', event => console.log(event.ids));
|
|
155
|
+
off();
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`insertMany` and `updateMany` emit one event for the whole operation, and nothing is emitted when nothing
|
|
159
|
+
changed. A listener that throws does not undo or interrupt the write.
|
|
160
|
+
|
|
161
|
+
## Databases and collections
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
sorla.listDatabases(); // ['tags', ...]
|
|
165
|
+
sorla.dropDb('tags');
|
|
166
|
+
sorla.db.listCollections(); // ['updatedTags', ...]
|
|
167
|
+
sorla.db.getCollection('stats'); // any collection, also when its name shadows a method
|
|
168
|
+
sorla.db.dropCollection('updatedTags');
|
|
169
|
+
sorla.db.getStats(); // { name, documents, collections: [{ name, documents }] }
|
|
170
|
+
```
|
|
171
|
+
|
|
45
172
|
## Find Operators
|
|
46
173
|
|
|
47
174
|
### $and
|
|
@@ -138,6 +265,22 @@ A document without the queried field does not match `$eq`, `$gt`, `$in`... but d
|
|
|
138
265
|
|
|
139
266
|
Unknown operators and logical operators that do not receive an array throw an error.
|
|
140
267
|
|
|
268
|
+
### $regex
|
|
269
|
+
Matches strings with a regular expression. `$options` takes the flags `i` (case insensitive), `m` and `s`.
|
|
270
|
+
A RegExp can be used directly as the value. Array fields match when one of their strings does.
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
const results = window.sorla.db.updatedTags.find({ name: { $regex: '^an', $options: 'i' } });
|
|
274
|
+
const same = window.sorla.db.updatedTags.find({ name: /^an/i });
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### $exists
|
|
278
|
+
`{ field: { $exists: true } }` matches documents that have the field, even when it is `null`;
|
|
279
|
+
`false` matches documents without it.
|
|
280
|
+
|
|
281
|
+
### Arrays
|
|
282
|
+
Equality is strict: `{ tags: 'dev' }` does not match `tags: ['dev']`. Use `{ tags: { $in: ['dev'] } }`.
|
|
283
|
+
|
|
141
284
|
## Comparison operators
|
|
142
285
|
|
|
143
286
|
### $eq
|