-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
769 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
--- | ||
label: Nitrite Collection | ||
icon: stack | ||
order: 17 | ||
--- | ||
label: Nitrite Collection | ||
order: 17 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
--- | ||
label: Introduction | ||
icon: info | ||
order: 17 | ||
--- | ||
|
||
`NitriteCollection` represents a named document collection stored in a Nitrite database. It persists documents in a Nitrite database. It is similar to a table in relational database or a collection in MongoDB. | ||
|
||
Each document in a collection is associated with a unique `NitriteId`. It exposes a set of methods to perform CRUD operations on documents. It also supports indexing and querying. It also supports event based notification on document changes. | ||
|
||
## Creating a Collection | ||
|
||
A `NitriteCollection` can be created using `Nitrite` class. You need to call `getCollection()` method on `Nitrite` class to get an instance of a `Future<NitriteCollection>`. | ||
|
||
If the collection does not exist, then it will be created automatically. If a collection with the same name already exists, then it will return the existing collection. | ||
|
||
```dart | ||
var db = await nitriteBuilder() | ||
.openOrCreate(); | ||
var collection = await db.getCollection("myCollection"); | ||
``` | ||
|
||
## Limitations on Collection Name | ||
|
||
A collection name cannot be `null` or empty string. It cannot contains any of the following characters: | ||
|
||
- `|` (pipe) | ||
- `:` (colon) | ||
- `+` (plus) | ||
|
||
The name also cannot be any of the following reserved words: | ||
|
||
- $nitrite_users | ||
- $nitrite_index_meta | ||
- $nitrite_index | ||
- $nitrite_meta_map | ||
- $nitrite_store_info | ||
- $nitrite_catalog | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,298 @@ | ||
--- | ||
label: Read Operations | ||
icon: search | ||
order: 15 | ||
--- | ||
|
||
## Find Operations | ||
|
||
You can search documents in a collection using `find()` method. There are several overloaded version of `find()` method using a filter or find options or both. You can also search a document using it's `NitriteId`. | ||
|
||
### Filters | ||
|
||
Nitrite uses filters to find documents in a collection. A filter is a simple expression which evaluates to `true` or `false`. More information about filters can be found [here](../filter.md). | ||
|
||
### Find All Documents | ||
|
||
You can find all documents in a collection by calling `find()`. It returns a `DocumentCursor` object. | ||
|
||
```dart | ||
var cursor = collection.find(); | ||
``` | ||
|
||
### Finding a Document Using NitriteId | ||
|
||
You can find a document using it's `NitriteId` by calling `getById()`. It takes a `NitriteId` as input parameter. It returns a `Future<Document?>` object if the document is found. Otherwise, it returns `null`. | ||
|
||
```dart | ||
var doc = await collection.getById(someNitriteId); | ||
``` | ||
|
||
### Finding a Document Using a Filter | ||
|
||
You can find a document using a filter. It takes a `Filter` object as input parameter. It returns a `DocumentCursor` object. | ||
|
||
If there is an index on the field specified in the filter, this operation will use the index to find the document. Otherwise, it will scan the entire collection to find the document. | ||
|
||
```dart | ||
var cursor = collection.find(where("firstName").eq("John")); | ||
``` | ||
|
||
### Finding a Document Using a Filter and Options | ||
|
||
You can find a document using a filter and options. It takes a `Filter` object as the first input parameter. It takes a `FindOptions` object as the second input parameter. It returns a `DocumentCursor` object. | ||
|
||
#### FindOptions | ||
|
||
`FindOptions` is a class that contains several options for find operation. It has the following options: | ||
|
||
- `limit`: It specifies the maximum number of documents to be returned by the find operation. | ||
- `skip`: It specifies the number of documents to be skipped from the beginning of the result set. | ||
- `orderBy`: It specifies a collection of fields to be sorted by, along with sort order for each field. The sort order can be `SortOrder.ascending` or `SortOrder.descending`. | ||
- `distinct`: It specifies if the find operation should return distinct documents. If this option is `true`, then it will return only the distinct documents. Otherwise, it will return all the documents matched by the filter. | ||
|
||
```dart | ||
var findOptions = FindOptions(); | ||
findOptions.setSkip(10) | ||
..setLimit(10) | ||
..thenOrderBy("firstName", SortOrder.descending) | ||
..withDistinct(true); | ||
var cursor = collection.find(filter: where("firstName").eq("John"), findOptions: findOptions); | ||
``` | ||
|
||
## DocumentCursor | ||
|
||
`DocumentCursor` represents a result set of a find operation. It provides methods to iterate over the result of a find operation and retrieve the documents. It also provides methods like projection, join etc. to get the desired result. | ||
|
||
### Iterating Over Documents | ||
|
||
The `DocumentCursor` extends `Stream<Document>`. So, you can iterate over the documents using await for loop. | ||
|
||
```dart | ||
var cursor = collection.find(where("firstName").eq("John")); | ||
await for (var doc in cursor) { | ||
// do something with the document | ||
} | ||
``` | ||
|
||
!!!info | ||
A `DocumentCursor` is a stream of document. It does not load all the documents in memory at once. It loads the documents in memory as needed. So, it is memory efficient. | ||
!!! | ||
|
||
### Getting the Documents | ||
|
||
You can get the documents from a `DocumentCursor` using `toList()` method. It returns a `Future<List<Document>>` object. | ||
|
||
```dart | ||
var cursor = collection.find(where("firstName").eq("John")); | ||
var docs = await cursor.toList(); | ||
``` | ||
|
||
### Getting the First Document | ||
|
||
You can get the first document from a `DocumentCursor` using `first` getter. It returns a `Future<Document?>` object. | ||
|
||
```dart | ||
var cursor = collection.find(where("firstName").eq("John")); | ||
var doc = await cursor.first; | ||
``` | ||
|
||
### Getting the Size of the Result Set | ||
|
||
You can get the size of the result set from a `DocumentCursor` using `length` getter. It returns a `Future<int>` object. | ||
|
||
```dart | ||
var cursor = collection.find(where("firstName").eq("John")); | ||
var size = await cursor.length; | ||
``` | ||
|
||
### Projection | ||
|
||
You can project a field or a set of fields from a `DocumentCursor` using `project()` method. It takes a `Document` as input parameter. It returns a `Stream<Document>` object. | ||
|
||
The document must contain only the fields that needs to be projected. The field values must be `null` or a nested document. The condition holds true for nested documents as well. | ||
|
||
Let's say you have a document like this: | ||
|
||
```json | ||
{ | ||
"firstName": "John", | ||
"lastName": "Doe", | ||
"address": { | ||
"street": "123 Main Street", | ||
"city": "New York" | ||
} | ||
} | ||
``` | ||
|
||
And you want to project only `lastName` and `address.street` fields. Then you can do it like this: | ||
|
||
```dart | ||
var cursor = collection.find(where("firstName").eq("John")); | ||
var projection = createDocument("lastName", null) | ||
..put("address", createDocument("street", null)); | ||
var projectedCursor = cursor.project(projection); | ||
``` | ||
|
||
The result set will contain only `lastName` and `address.street` fields. | ||
|
||
```json | ||
[ | ||
{ | ||
"lastName": "Doe", | ||
"address": { | ||
"street": "123 Main Street" | ||
} | ||
} | ||
] | ||
``` | ||
|
||
### Join | ||
|
||
You can join two `DocumentCursor` using `leftJoin()` method. It takes another `DocumentCursor` as input parameter along with a `Lookup` object. It returns a `Stream<Document>` object. | ||
|
||
The join operation is similar to SQL left outer join operation. It takes two cursors and a lookup object. The lookup object contains the join condition. | ||
|
||
Let's say you have two collections `users` and `orders`. The `users` collection contains the following documents: | ||
|
||
```json | ||
{ | ||
"userId": 1, | ||
"firstName": "John", | ||
"lastName": "Doe" | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"userId": 2, | ||
"firstName": "Jane", | ||
"lastName": "Doe" | ||
} | ||
``` | ||
|
||
And the `orders` collection contains the following documents: | ||
|
||
```json | ||
{ | ||
"orderId": 1, | ||
"userId": 1, | ||
"orderDate": "2018-01-01" | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"orderId": 2, | ||
"userId": 1, | ||
"orderDate": "2018-01-02" | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"orderId": 3, | ||
"userId": 2, | ||
"orderDate": "2018-01-03" | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"orderId": 4, | ||
"userId": 2, | ||
"orderDate": "2018-01-04" | ||
} | ||
``` | ||
|
||
And you want to join these two collections on `userId` field. Then you can do it like this: | ||
|
||
```dart | ||
var userCollection = await db.collection("users"); | ||
var orderCollection = await db.collection("orders"); | ||
var users = userCollection.find(); | ||
var orders = orderCollection.find(); | ||
var lookup = Lookup(); | ||
lookup.setLocalField("userId"); | ||
lookup.setForeignField("userId"); | ||
lookup.setTargetField("orders"); | ||
var joinedCursor = users.leftJoin(orders, lookup); | ||
``` | ||
|
||
The result set will contain the following documents: | ||
|
||
```json | ||
{ | ||
"userId": 1, | ||
"firstName": "John", | ||
"lastName": "Doe", | ||
"orders": [ | ||
{ | ||
"orderId": 1, | ||
"userId": 1, | ||
"orderDate": "2018-01-01" | ||
}, | ||
{ | ||
"orderId": 2, | ||
"userId": 1, | ||
"orderDate": "2018-01-02" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"userId": 2, | ||
"firstName": "Jane", | ||
"lastName": "Doe", | ||
"orders": [ | ||
{ | ||
"orderId": 3, | ||
"userId": 2, | ||
"orderDate": "2018-01-03" | ||
}, | ||
{ | ||
"orderId": 4, | ||
"userId": 2, | ||
"orderDate": "2018-01-04" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
### FindPlan | ||
|
||
`FindPlan` is a class that contains the execution plan of a find operation. It has the following properties: | ||
|
||
- `byIdFilter`: It contains the filter for finding a document using `NitriteId`. | ||
- `indexScanFilter`: It contains the filter for finding a document using index. | ||
- `collectionScanFilter`: It contains the filter for finding a document using full scan. | ||
- `indexDescriptor`: It contains the index descriptor for finding a document using index. | ||
- `indexScanOrder`: It contains the sort order for finding a document using index. | ||
- `blockingSortOrder`: It contains the sort order for finding a document using full scan. | ||
- `skip`: It contains the number of documents to be skipped from the beginning of the result set. | ||
- `limit`: It contains the maximum number of documents to be returned by the find operation. | ||
- `distinct`: It specifies if the find operation returns distinct documents. | ||
- `subPlans`: It contains the sub plans for finding a document using `or` filter. | ||
|
||
You can get the execution plan of a find operation using `findPlan` getter. It returns a `Future<FindPlan>` object. | ||
|
||
```dart | ||
var cursor = collection.find(where("firstName").eq("John")); | ||
var findPlan = await cursor.findPlan; | ||
``` | ||
|
||
|
||
|
Oops, something went wrong.